Skip to content

Commit 885d5bb

Browse files
committed
Add proper unit tests for event-aggregator pattern
1 parent 1b74e0f commit 885d5bb

9 files changed

Lines changed: 355 additions & 0 deletions

File tree

event-aggregator/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,10 @@
1313
<artifactId>junit</artifactId>
1414
<scope>test</scope>
1515
</dependency>
16+
<dependency>
17+
<groupId>org.mockito</groupId>
18+
<artifactId>mockito-core</artifactId>
19+
<scope>test</scope>
20+
</dependency>
1621
</dependencies>
1722
</project>
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package com.iluwatar.event.aggregator;
2+
3+
import org.junit.Test;
4+
5+
import java.util.Objects;
6+
import java.util.function.Function;
7+
import java.util.function.Supplier;
8+
9+
import static org.mockito.Matchers.eq;
10+
import static org.mockito.Mockito.mock;
11+
import static org.mockito.Mockito.times;
12+
import static org.mockito.Mockito.verify;
13+
import static org.mockito.Mockito.verifyNoMoreInteractions;
14+
import static org.mockito.Mockito.verifyZeroInteractions;
15+
16+
/**
17+
* Date: 12/12/15 - 10:58 PM
18+
*
19+
* @author Jeroen Meulemeester
20+
*/
21+
public abstract class EventEmitterTest<E extends EventEmitter> {
22+
23+
/**
24+
* Factory used to create a new instance of the test object with a default observer
25+
*/
26+
private final Function<EventObserver, E> factoryWithDefaultObserver;
27+
28+
/**
29+
* Factory used to create a new instance of the test object without passing a default observer
30+
*/
31+
private final Supplier<E> factoryWithoutDefaultObserver;
32+
33+
/**
34+
* The day of the week an event is expected
35+
*/
36+
private final Weekday specialDay;
37+
38+
/**
39+
* The expected event, emitted on the special day
40+
*/
41+
private final Event event;
42+
43+
/**
44+
* Create a new event emitter test, using the given test object factories, special day and event
45+
*/
46+
EventEmitterTest(final Weekday specialDay, final Event event,
47+
final Function<EventObserver, E> factoryWithDefaultObserver,
48+
final Supplier<E> factoryWithoutDefaultObserver) {
49+
50+
this.specialDay = specialDay;
51+
this.event = event;
52+
this.factoryWithDefaultObserver = Objects.requireNonNull(factoryWithDefaultObserver);
53+
this.factoryWithoutDefaultObserver = Objects.requireNonNull(factoryWithoutDefaultObserver);
54+
}
55+
56+
/**
57+
* Go over every day of the month, and check if the event is emitted on the given day. This test
58+
* is executed twice, once without a default emitter and once with
59+
*/
60+
@Test
61+
public void testAllDays() {
62+
testAllDaysWithoutDefaultObserver(specialDay, event);
63+
testAllDaysWithDefaultObserver(specialDay, event);
64+
}
65+
66+
/**
67+
* Go over every day of the month, and check if the event is emitted on the given day. Use an
68+
* event emitter without a default observer
69+
*
70+
* @param specialDay The special day on which an event is emitted
71+
* @param event The expected event emitted by the test object
72+
*/
73+
private void testAllDaysWithoutDefaultObserver(final Weekday specialDay, final Event event) {
74+
final EventObserver observer1 = mock(EventObserver.class);
75+
final EventObserver observer2 = mock(EventObserver.class);
76+
77+
final E emitter = this.factoryWithoutDefaultObserver.get();
78+
emitter.registerObserver(observer1);
79+
emitter.registerObserver(observer2);
80+
81+
testAllDays(specialDay, event, emitter, observer1, observer2);
82+
}
83+
84+
/**
85+
* Go over every day of the month, and check if the event is emitted on the given day.
86+
*
87+
* @param specialDay The special day on which an event is emitted
88+
* @param event The expected event emitted by the test object
89+
*/
90+
private void testAllDaysWithDefaultObserver(final Weekday specialDay, final Event event) {
91+
final EventObserver defaultObserver = mock(EventObserver.class);
92+
final EventObserver observer1 = mock(EventObserver.class);
93+
final EventObserver observer2 = mock(EventObserver.class);
94+
95+
final E emitter = this.factoryWithDefaultObserver.apply(defaultObserver);
96+
emitter.registerObserver(observer1);
97+
emitter.registerObserver(observer2);
98+
99+
testAllDays(specialDay, event, emitter, defaultObserver, observer1, observer2);
100+
}
101+
102+
/**
103+
* Pass each week of the day, day by day to the event emitter and verify of the given observers
104+
* received the correct event on the special day.
105+
*
106+
* @param specialDay The special day on which an event is emitted
107+
* @param event The expected event emitted by the test object
108+
* @param emitter The event emitter
109+
* @param observers The registered observer mocks
110+
*/
111+
private void testAllDays(final Weekday specialDay, final Event event, final E emitter,
112+
final EventObserver... observers) {
113+
114+
for (final Weekday weekday : Weekday.values()) {
115+
// Pass each week of the day, day by day to the event emitter
116+
emitter.timePasses(weekday);
117+
118+
if (weekday == specialDay) {
119+
// On a special day, every observer should have received the event
120+
for (final EventObserver observer : observers) {
121+
verify(observer, times(1)).onEvent(eq(event));
122+
}
123+
} else {
124+
// On any other normal day, the observers should have received nothing at all
125+
verifyZeroInteractions(observers);
126+
}
127+
}
128+
129+
// The observers should not have received any additional events after the week
130+
verifyNoMoreInteractions(observers);
131+
}
132+
133+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.iluwatar.event.aggregator;
2+
3+
import org.junit.Test;
4+
5+
import static org.junit.Assert.assertFalse;
6+
import static org.junit.Assert.assertNotNull;
7+
8+
/**
9+
* Date: 12/12/15 - 2:52 PM
10+
*
11+
* @author Jeroen Meulemeester
12+
*/
13+
public class EventTest {
14+
15+
/**
16+
* Verify if every event has a non-null, non-empty description
17+
*/
18+
@Test
19+
public void testToString() {
20+
for (final Event event : Event.values()) {
21+
final String toString = event.toString();
22+
assertNotNull(toString);
23+
assertFalse(toString.trim().isEmpty());
24+
}
25+
}
26+
27+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.iluwatar.event.aggregator;
2+
3+
import org.junit.After;
4+
import org.junit.Before;
5+
import org.junit.Test;
6+
7+
import java.io.PrintStream;
8+
9+
import static org.mockito.Mockito.mock;
10+
import static org.mockito.Mockito.times;
11+
import static org.mockito.Mockito.verify;
12+
import static org.mockito.Mockito.verifyNoMoreInteractions;
13+
import static org.mockito.Mockito.verifyZeroInteractions;
14+
15+
/**
16+
* Date: 12/12/15 - 3:04 PM
17+
*
18+
* @author Jeroen Meulemeester
19+
*/
20+
public class KingJoffreyTest {
21+
22+
/**
23+
* The mocked standard out {@link PrintStream}, required since {@link KingJoffrey} does nothing
24+
* except for writing to std-out using {@link System#out}
25+
*/
26+
private final PrintStream stdOutMock = mock(PrintStream.class);
27+
28+
/**
29+
* Keep the original std-out so it can be restored after the test
30+
*/
31+
private final PrintStream stdOutOrig = System.out;
32+
33+
/**
34+
* Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test
35+
*/
36+
@Before
37+
public void setUp() {
38+
System.setOut(this.stdOutMock);
39+
}
40+
41+
/**
42+
* Removed the mocked std-out {@link PrintStream} again from the {@link System} class
43+
*/
44+
@After
45+
public void tearDown() {
46+
System.setOut(this.stdOutOrig);
47+
}
48+
49+
/**
50+
* Test if {@link KingJoffrey} tells us what event he received
51+
*/
52+
@Test
53+
public void testOnEvent() {
54+
final KingJoffrey kingJoffrey = new KingJoffrey();
55+
56+
for (final Event event : Event.values()) {
57+
verifyZeroInteractions(this.stdOutMock);
58+
kingJoffrey.onEvent(event);
59+
60+
final String expectedMessage = "Received event from the King's Hand: " + event.toString();
61+
verify(this.stdOutMock, times(1)).println(expectedMessage);
62+
verifyNoMoreInteractions(this.stdOutMock);
63+
}
64+
65+
}
66+
67+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.iluwatar.event.aggregator;
2+
3+
import org.junit.Test;
4+
5+
import static org.mockito.Matchers.eq;
6+
import static org.mockito.Mockito.mock;
7+
import static org.mockito.Mockito.times;
8+
import static org.mockito.Mockito.verify;
9+
import static org.mockito.Mockito.verifyNoMoreInteractions;
10+
import static org.mockito.Mockito.verifyZeroInteractions;
11+
12+
/**
13+
* Date: 12/12/15 - 10:57 AM
14+
*
15+
* @author Jeroen Meulemeester
16+
*/
17+
public class KingsHandTest extends EventEmitterTest<KingsHand> {
18+
19+
/**
20+
* Create a new test instance, using the correct object factory
21+
*/
22+
public KingsHandTest() {
23+
super(null, null, KingsHand::new, KingsHand::new);
24+
}
25+
26+
/**
27+
* The {@link KingsHand} is both an {@EventEmitter} as an {@link EventObserver} so verify if every
28+
* event received is passed up to it's superior, in most cases {@link KingJoffrey} but now just a
29+
* mocked observer.
30+
*/
31+
@Test
32+
public void testPassThrough() throws Exception {
33+
final EventObserver observer = mock(EventObserver.class);
34+
final KingsHand kingsHand = new KingsHand(observer);
35+
36+
// The kings hand should not pass any events before he received one
37+
verifyZeroInteractions(observer);
38+
39+
// Verify if each event is passed on to the observer, nothing less, nothing more.
40+
for (final Event event : Event.values()) {
41+
kingsHand.onEvent(event);
42+
verify(observer, times(1)).onEvent(eq(event));
43+
verifyNoMoreInteractions(observer);
44+
}
45+
46+
}
47+
48+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.iluwatar.event.aggregator;
2+
3+
/**
4+
* Date: 12/12/15 - 10:57 AM
5+
*
6+
* @author Jeroen Meulemeester
7+
*/
8+
public class LordBaelishTest extends EventEmitterTest<LordBaelish> {
9+
10+
/**
11+
* Create a new test instance, using the correct object factory
12+
*/
13+
public LordBaelishTest() {
14+
super(Weekday.FRIDAY, Event.STARK_SIGHTED, LordBaelish::new, LordBaelish::new);
15+
}
16+
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.iluwatar.event.aggregator;
2+
3+
/**
4+
* Date: 12/12/15 - 10:57 AM
5+
*
6+
* @author Jeroen Meulemeester
7+
*/
8+
public class LordVarysTest extends EventEmitterTest<LordVarys> {
9+
10+
/**
11+
* Create a new test instance, using the correct object factory
12+
*/
13+
public LordVarysTest() {
14+
super(Weekday.SATURDAY, Event.TRAITOR_DETECTED, LordVarys::new, LordVarys::new);
15+
}
16+
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.iluwatar.event.aggregator;
2+
3+
/**
4+
* Date: 12/12/15 - 10:57 AM
5+
*
6+
* @author Jeroen Meulemeester
7+
*/
8+
public class ScoutTest extends EventEmitterTest<Scout> {
9+
10+
/**
11+
* Create a new test instance, using the correct object factory
12+
*/
13+
public ScoutTest() {
14+
super(Weekday.TUESDAY, Event.WARSHIPS_APPROACHING, Scout::new, Scout::new);
15+
}
16+
17+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.iluwatar.event.aggregator;
2+
3+
import org.junit.Test;
4+
5+
import static org.junit.Assert.assertEquals;
6+
import static org.junit.Assert.assertNotNull;
7+
8+
/**
9+
* Date: 12/12/15 - 2:12 PM
10+
*
11+
* @author Jeroen Meulemeester
12+
*/
13+
public class WeekdayTest {
14+
15+
@Test
16+
public void testToString() throws Exception {
17+
for (final Weekday weekday : Weekday.values()) {
18+
final String toString = weekday.toString();
19+
assertNotNull(toString);
20+
assertEquals(weekday.name(), toString.toUpperCase());
21+
}
22+
}
23+
24+
}

0 commit comments

Comments
 (0)