Skip to content

Commit

Permalink
Feat: EventManager refactor + test
Browse files Browse the repository at this point in the history
Added validation for adding subscribers, and refactored test class for eventmanager. Removed unused getname method for eventchannel, and added validator ruleset for valid week.
  • Loading branch information
tommyah committed May 25, 2026
1 parent dccb4f8 commit e75440c
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,4 @@
* <p>Decreases coupling and enables testing of event types.</p>
* */
public interface EventChannel {

/**
* Getter method for enum name.
*
* @return String name of enum.
* */
String getName();
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,20 @@ public final class EventManager {
* @param subscriber the {@link EventSubscriber} object to add.
* @param eventChannel the {@link EventChannel} type this subscriber should subscribe to.
*
*
* @throws IllegalArgumentException if subscriber is already subscribed to event channel,
* or if parameters are null.
*/
public void addSubscriber(final EventSubscriber subscriber, final EventChannel eventChannel) {
public void addSubscriber(final EventSubscriber subscriber, final EventChannel eventChannel)
throws IllegalArgumentException {
if (subscriber == null || eventChannel == null) {
throw new IllegalArgumentException("Parameters cannot be null!");
}

List<EventSubscriber> subscribers = subscriberMap.get(eventChannel);
if (subscribers != null && subscribers.contains(subscriber)) {
throw new IllegalArgumentException("Subscriber already subscribed to event channel!");
}

subscriberMap.computeIfAbsent(eventChannel, k -> new ArrayList<>()).add(subscriber);
}

Expand All @@ -49,9 +60,9 @@ public void addSubscriber(final EventSubscriber subscriber, final EventChannel e
*/
public <T> void invokeEvent(final EventData<T> data)
throws IllegalArgumentException {
if (data == null || !subscriberMap.containsKey(data.channel())) {
if (data == null || data.data() == null) {
throw new IllegalArgumentException(
"No subscriber listening to this event!"
"Data cannot be null!"
);
} else {
for (EventSubscriber e : subscriberMap.get(data.channel())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,4 @@ public enum EventType implements EventChannel {
*
*/
SELECT_STOCK_FOR_MINIGAME;

/**
* {@inheritDoc}
* */
@Override
public String getName() {
return this.name();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ public enum Validator {
* */
VALID_POSITIVE_INT(VALID_INT.validationRule.and(s ->
Integer.parseInt(s) >= 0), "Number is not positive!"),

/**
* Rule that checks if a string represents a valid week. (Greater than 1).
* */
VALID_WEEK(VALID_POSITIVE_INT.validationRule.and(s ->
Integer.parseInt(s) > 0), "Invalid week"),
/**
* Rule that checks if string is not empty,
* and if it can be parsed into a {@link LocalDate} object.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,99 +1,176 @@
package edu.ntnu.idi.idatt2003.g40.mappe.service.event;

import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewData;
import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewEnum;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class EventManagerTest {
private enum TestEventTypes implements EventChannel {
/**
* Test event type 1.
* */
TEST_TYPE_1,

/**
* Test event type 2.
* */
TEST_TYPE_2,

/**
* Test event type 3 (Used by both subscribers).
* */
TEST_TYPE_3;

@Override
public String getName() {
return this.name();
}
}

private GenericEventPublisher testEventPublisher;
private GenericEventPublisher testEventPublisher2;
private GenericEventPublisher testEventPublisher3;

private GenericEventSubscriber testEventSubscriber;
private GenericEventSubscriber testEventSubscriber2;

private EventManager testEventManager;
private SampleEventSubscriber sampleEventSubscriber1;
private SampleEventSubscriber sampleEventSubscriber2;

@BeforeEach
void setUp() {
testEventManager = new EventManager();

testEventSubscriber = new GenericEventSubscriber();
testEventSubscriber2 = new GenericEventSubscriber();
sampleEventSubscriber1 = new SampleEventSubscriber();
sampleEventSubscriber2 = new SampleEventSubscriber();

testEventManager.addSubscriber(sampleEventSubscriber1, TestEventTypes.TEST_TYPE_1);
testEventManager.addSubscriber(sampleEventSubscriber1, TestEventTypes.TEST_TYPE_3);

testEventManager.addSubscriber(sampleEventSubscriber2, TestEventTypes.TEST_TYPE_2);
testEventManager.addSubscriber(sampleEventSubscriber2, TestEventTypes.TEST_TYPE_3);
}

testEventPublisher = new GenericEventPublisher(testEventManager, TestEventTypes.TEST_TYPE_1);
testEventPublisher2 = new GenericEventPublisher(testEventManager, TestEventTypes.TEST_TYPE_2);
testEventPublisher3 = new GenericEventPublisher(testEventManager, TestEventTypes.TEST_TYPE_3);
@Test
void addingSubscriberNullParametersThrowsException() {
assertThrows(IllegalArgumentException.class,
() -> testEventManager.addSubscriber(
null,
TestEventTypes.TEST_TYPE_2));

assertThrows(IllegalArgumentException.class,
() -> testEventManager.addSubscriber(
sampleEventSubscriber1,
null));

// Will only throw exception if sample event subscriber 1 is duplicate.
assertDoesNotThrow(
() -> testEventManager.addSubscriber(
sampleEventSubscriber1,
TestEventTypes.TEST_TYPE_2));

testEventManager.addSubscriber(testEventSubscriber, TestEventTypes.TEST_TYPE_1);
testEventManager.addSubscriber(testEventSubscriber2, TestEventTypes.TEST_TYPE_2);
}

@Test
void addingDuplicateSubscriberForSameChannelThrowsException() {
assertDoesNotThrow(
() -> testEventManager.addSubscriber(
sampleEventSubscriber1,
TestEventTypes.TEST_TYPE_2));

assertThrows(IllegalArgumentException.class,
() -> testEventManager.addSubscriber(
sampleEventSubscriber1,
TestEventTypes.TEST_TYPE_1));
}

@Test
void firedEventCaughtByCorrectSubscriber() {
assertFalse(testEventSubscriber.invokedEvent);
testEventPublisher.fireEvent();
assertTrue(testEventSubscriber.invokedEvent);
String dataToSend = "Data for type 1";

assertFalse(sampleEventSubscriber1.getInvoked());
assertNull(sampleEventSubscriber1.getLastReceivedData());

EventData<String> eventData = new EventData<>(
TestEventTypes.TEST_TYPE_1,
dataToSend
);
testEventManager.invokeEvent(eventData);

assertTrue(sampleEventSubscriber1.getInvoked());
assertEquals(dataToSend, sampleEventSubscriber1.getLastReceivedData());
}

@Test
void firedEventNotCaughtByIncorrectSubscriber() {
assertFalse(testEventSubscriber.invokedEvent);
testEventPublisher2.fireEvent();
assertFalse(testEventSubscriber.invokedEvent);
String dataToSend = "Data for type 1";

assertFalse(sampleEventSubscriber1.getInvoked());
assertNull(sampleEventSubscriber1.getLastReceivedData());
assertFalse(sampleEventSubscriber2.getInvoked());
assertNull(sampleEventSubscriber2.getLastReceivedData());

EventData<String> eventData = new EventData<>(
TestEventTypes.TEST_TYPE_2,
dataToSend
);
testEventManager.invokeEvent(eventData);

assertFalse(sampleEventSubscriber1.getInvoked());
assertNull(sampleEventSubscriber1.getLastReceivedData());

assertTrue(sampleEventSubscriber2.getInvoked());
assertEquals(dataToSend, sampleEventSubscriber2.getLastReceivedData());
}

@Test
void firedEventThrowsErrorWhenNoSubscribers() {
assertFalse(testEventSubscriber.invokedEvent);
assertThrows(IllegalArgumentException.class, () -> {
testEventPublisher3.fireEvent();
});
assertFalse(testEventSubscriber.invokedEvent);
}
void firedEventsWithMultipleSubscribersCaughtByAllSubscribers() {
String dataToSend = "Data for type 1";

private class GenericEventPublisher implements EventPublisher {
assertFalse(sampleEventSubscriber1.getInvoked());
assertNull(sampleEventSubscriber1.getLastReceivedData());
assertFalse(sampleEventSubscriber2.getInvoked());
assertNull(sampleEventSubscriber2.getLastReceivedData());

private final ViewData viewData;
private final EventData<ViewData> eventData;
private final EventManager eventManager;
EventData<String> eventData = new EventData<>(
TestEventTypes.TEST_TYPE_3,
dataToSend
);
testEventManager.invokeEvent(eventData);

public GenericEventPublisher(final EventManager eventManager, final TestEventTypes eventType) {
viewData = new ViewData(ViewEnum.IN_GAME);
eventData = new EventData<ViewData>(eventType, viewData);
this.eventManager = eventManager;
}
assertTrue(sampleEventSubscriber1.getInvoked());
assertEquals(dataToSend, sampleEventSubscriber1.getLastReceivedData());

public void fireEvent() {
invoke(eventData, eventManager);
}
assertTrue(sampleEventSubscriber2.getInvoked());
assertEquals(dataToSend, sampleEventSubscriber2.getLastReceivedData());
}

@Override
public <T> void invoke(EventData<T> data, EventManager eventManager) {
eventManager.invokeEvent(data);
}
@Test
void firedEventThrowsErrorWhenDataIsNull() {

EventData<String> invalidEventData = new EventData<>(
TestEventTypes.TEST_TYPE_1,
null
);

assertThrows(IllegalArgumentException.class,
() -> testEventManager.invokeEvent(null));

assertThrows(IllegalArgumentException.class,
() -> testEventManager.invokeEvent(invalidEventData));
}

private class GenericEventSubscriber implements EventSubscriber {
public boolean invokedEvent = false;
private static class SampleEventSubscriber implements EventSubscriber {
private boolean invokedEvent = false;
private Object lastReceivedData = null;

@Override
public <T> void handleEvent(EventData<T> data) {
public <T> void handleEvent(final EventData<T> data) {
invokedEvent = true;
lastReceivedData = data.data();
}

private boolean getInvoked() {
return invokedEvent;
}

private Object getLastReceivedData() {
return lastReceivedData;
}
}
}

0 comments on commit e75440c

Please sign in to comment.