From 09c5dd20bebd59149f358e579f2917d8a8b74243 Mon Sep 17 00:00:00 2001 From: damon Date: Mon, 18 May 2026 23:55:47 +0800 Subject: [PATCH] Add unit tests for EventHandler functionality and implement UserEventCounterHandler --- .../neroyun/mediator/EventHandlerTest.java | 158 ++++++++++++++++++ .../mediator/PipelinedMediatorTest.java | 14 +- .../mediator/UserEventCounterHandler.java | 28 ++++ 3 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 src/test/java/com/neroyun/mediator/EventHandlerTest.java create mode 100644 src/test/java/com/neroyun/mediator/UserEventCounterHandler.java diff --git a/src/test/java/com/neroyun/mediator/EventHandlerTest.java b/src/test/java/com/neroyun/mediator/EventHandlerTest.java new file mode 100644 index 0000000..0d2bdf2 --- /dev/null +++ b/src/test/java/com/neroyun/mediator/EventHandlerTest.java @@ -0,0 +1,158 @@ +package com.neroyun.mediator; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.concurrent.Executors; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * Unit tests for Event Handler functionality. + * Tests event handling, event publishing, and multiple handlers for a single event. + */ +public class EventHandlerTest { + + private Mediator mediator; + private UserEventCounterHandler userEventCounter; + + @BeforeEach + void setUp() { + // Clear any previous state + UserStore.getInstance().clear(); + + // Create handler instances + userEventCounter = new UserEventCounterHandler(); + + // Setup mediator with handlers + mediator = new PipelinedMediator() + .use(() -> Stream.of( + new UserCreatedEventHandler(), + userEventCounter + )) + .use(() -> Executors.newFixedThreadPool(2)); + } + + @Test + void testUserCreatedEventHandler() { + // Arrange + UserCreatedEvent event = new UserCreatedEvent(123L, "Jane Doe"); + UserCreatedEventHandler handler = new UserCreatedEventHandler(); + + // Act + Void result = handler.handle(event); + + // Assert + assertNull(result, "Event handler should return null (Void)"); + } + + @Test + void testEventHandlerReturnsVoid() { + // Arrange + UserCreatedEvent event = new UserCreatedEvent(456L, "John Smith"); + UserCreatedEventHandler handler = new UserCreatedEventHandler(); + + // Act + Void result = handler.handle(event); + + // Assert + assertNull(result, "Event handler should return null (Void)"); + } + + @Test + void testEventHandlerMatches() { + // Arrange + UserCreatedEvent event = new UserCreatedEvent(1L, "Test User"); + UserCreatedEventHandler handler = new UserCreatedEventHandler(); + + // Act + boolean matches = handler.matches(event); + + // Assert + assertTrue(matches, "Handler should match its own event type"); + } + + @Test + void testEventPublishDoesNotThrow() { + // Arrange + UserCreatedEvent event = new UserCreatedEvent(999L, "No Exception User"); + + // Act & Assert + assertDoesNotThrow(() -> mediator.publish(event), "Publishing an event should not throw an exception"); + } + + @Test + void testMultipleHandlersForSameEvent() { + // Arrange + UserCreatedEvent event = new UserCreatedEvent(100L, "Multiple Handlers User"); + + // Act + mediator.publish(event); + + // Give handlers time to process (since they run asynchronously) + try { + Thread.sleep(100); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + + // Assert + assertTrue(userEventCounter.getCount() > 0, "Counter handler should have been invoked"); + } + + @Test + void testMultipleEventsHandledInOrder() { + // Arrange + UserCreatedEvent event1 = new UserCreatedEvent(1L, "First User"); + UserCreatedEvent event2 = new UserCreatedEvent(2L, "Second User"); + UserCreatedEvent event3 = new UserCreatedEvent(3L, "Third User"); + + // Act + mediator.publish(event1); + mediator.publish(event2); + mediator.publish(event3); + + // Give handlers time to process + try { + Thread.sleep(200); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + + // Assert + assertEquals(3, userEventCounter.getCount(), "Handler should have handled 3 events"); + } + + @Test + void testEventHandlerWithNullParameters() { + // Arrange & Act & Assert + assertThrows(IllegalArgumentException.class, + () -> mediator.publish(null), + "Publishing null event should throw IllegalArgumentException"); + } + + @Test + void testUserCreatedEventImmutability() { + // Arrange + Long id = 42L; + String name = "Test User"; + + // Act + UserCreatedEvent event = new UserCreatedEvent(id, name); + + // Assert + assertEquals(id, event.id(), "Event should store the correct id"); + assertEquals(name, event.name(), "Event should store the correct name"); + } + + @Test + void testEventImplementsEventInterface() { + // Arrange + UserCreatedEvent event = new UserCreatedEvent(1L, "Test"); + + // Assert + assertInstanceOf(Event.class, event, "UserCreatedEvent should implement Event interface"); + } +} + diff --git a/src/test/java/com/neroyun/mediator/PipelinedMediatorTest.java b/src/test/java/com/neroyun/mediator/PipelinedMediatorTest.java index efb13c0..ab3e195 100644 --- a/src/test/java/com/neroyun/mediator/PipelinedMediatorTest.java +++ b/src/test/java/com/neroyun/mediator/PipelinedMediatorTest.java @@ -17,11 +17,23 @@ public PipelinedMediatorTest() { } @Test - public void testMediator() { + void testMediator() { mediator.send(new UserCreateCommand("John Doe", "johndoe@sample.com")); var users = UserStore.getInstance().getUsers(); assert users.size() == 1; assert users.get(0).name().equals("John Doe"); } + + @Test + void testEventPublish() { + // Arrange + UserCreatedEvent event = new UserCreatedEvent(1234L, "Event Test User"); + + // Act & Assert - should not throw exception + mediator.publish(event); + + // Event publishing is asynchronous, so we just verify it doesn't throw + assert true; + } } diff --git a/src/test/java/com/neroyun/mediator/UserEventCounterHandler.java b/src/test/java/com/neroyun/mediator/UserEventCounterHandler.java new file mode 100644 index 0000000..0f96b4f --- /dev/null +++ b/src/test/java/com/neroyun/mediator/UserEventCounterHandler.java @@ -0,0 +1,28 @@ +package com.neroyun.mediator; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * A test event handler that counts how many UserCreatedEvent instances it has handled. + * Uses AtomicInteger for thread-safe counting. + */ +public class UserEventCounterHandler implements Handler { + private final AtomicInteger counter = new AtomicInteger(0); + + @Override + public Void handle(UserCreatedEvent message) { + counter.incrementAndGet(); + System.out.printf("UserEventCounterHandler: Counted event for user %s (Total: %d)\n", + message.name(), counter.get()); + return null; + } + + public int getCount() { + return counter.get(); + } + + public void reset() { + counter.set(0); + } +} +