Skip to content

Commit 3e20a2a

Browse files
committed
Added tests for observer pattern
1 parent 4c938ab commit 3e20a2a

6 files changed

Lines changed: 253 additions & 0 deletions

File tree

observer/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,10 @@
1414
<artifactId>junit</artifactId>
1515
<scope>test</scope>
1616
</dependency>
17+
<dependency>
18+
<groupId>org.mockito</groupId>
19+
<artifactId>mockito-core</artifactId>
20+
<scope>test</scope>
21+
</dependency>
1722
</dependencies>
1823
</project>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.iluwatar.observer;
2+
3+
import org.junit.runner.RunWith;
4+
import org.junit.runners.Parameterized;
5+
6+
import java.util.ArrayList;
7+
import java.util.Collection;
8+
9+
/**
10+
* Date: 12/27/15 - 12:07 PM
11+
*
12+
* @author Jeroen Meulemeester
13+
*/
14+
@RunWith(Parameterized.class)
15+
public class HobbitsTest extends WeatherObserverTest<Hobbits> {
16+
17+
@Parameterized.Parameters
18+
public static Collection<Object[]> data() {
19+
final ArrayList<Object[]> testData = new ArrayList<>();
20+
testData.add(new Object[]{WeatherType.SUNNY, "The happy hobbits bade in the warm sun."});
21+
testData.add(new Object[]{WeatherType.RAINY, "The hobbits look for cover from the rain."});
22+
testData.add(new Object[]{WeatherType.WINDY, "The hobbits hold their hats tightly in the windy weather."});
23+
testData.add(new Object[]{WeatherType.COLD, "The hobbits are shivering in the cold weather."});
24+
return testData;
25+
}
26+
27+
/**
28+
* Create a new test with the given weather and expected response
29+
*
30+
* @param weather The weather that should be unleashed on the observer
31+
* @param response The expected response from the observer
32+
*/
33+
public HobbitsTest(final WeatherType weather, final String response) {
34+
super(weather, response, Hobbits::new);
35+
}
36+
37+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.iluwatar.observer;
2+
3+
import org.junit.runner.RunWith;
4+
import org.junit.runners.Parameterized;
5+
6+
import java.util.ArrayList;
7+
import java.util.Collection;
8+
9+
/**
10+
* Date: 12/27/15 - 12:07 PM
11+
*
12+
* @author Jeroen Meulemeester
13+
*/
14+
@RunWith(Parameterized.class)
15+
public class OrcsTest extends WeatherObserverTest<Orcs> {
16+
17+
@Parameterized.Parameters
18+
public static Collection<Object[]> data() {
19+
final ArrayList<Object[]> testData = new ArrayList<>();
20+
testData.add(new Object[]{WeatherType.SUNNY, "The sun hurts the orcs' eyes."});
21+
testData.add(new Object[]{WeatherType.RAINY, "The orcs are dripping wet."});
22+
testData.add(new Object[]{WeatherType.WINDY, "The orc smell almost vanishes in the wind."});
23+
testData.add(new Object[]{WeatherType.COLD, "The orcs are freezing cold."});
24+
return testData;
25+
}
26+
27+
/**
28+
* Create a new test with the given weather and expected response
29+
*
30+
* @param weather The weather that should be unleashed on the observer
31+
* @param response The expected response from the observer
32+
*/
33+
public OrcsTest(final WeatherType weather, final String response) {
34+
super(weather, response, Orcs::new);
35+
}
36+
37+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.iluwatar.observer;
2+
3+
import org.junit.After;
4+
import org.junit.Before;
5+
6+
import java.io.PrintStream;
7+
8+
import static org.mockito.Mockito.mock;
9+
10+
/**
11+
* Date: 12/27/15 - 12:16 PM
12+
*
13+
* @author Jeroen Meulemeester
14+
*/
15+
public abstract class StdOutTest {
16+
17+
/**
18+
* The mocked standard out {@link PrintStream}, required since changes in the weather doesn't has
19+
* any influence on any other accessible objects, except for writing to std-out using {@link
20+
* System#out}
21+
*/
22+
private final PrintStream stdOutMock = mock(PrintStream.class);
23+
24+
/**
25+
* Keep the original std-out so it can be restored after the test
26+
*/
27+
private final PrintStream stdOutOrig = System.out;
28+
29+
/**
30+
* Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test
31+
*/
32+
@Before
33+
public void setUp() {
34+
System.setOut(this.stdOutMock);
35+
}
36+
37+
/**
38+
* Removed the mocked std-out {@link PrintStream} again from the {@link System} class
39+
*/
40+
@After
41+
public void tearDown() {
42+
System.setOut(this.stdOutOrig);
43+
}
44+
45+
/**
46+
* Get the mocked stdOut {@link PrintStream}
47+
*
48+
* @return The stdOut print stream mock, renewed before each test
49+
*/
50+
final PrintStream getStdOutMock() {
51+
return this.stdOutMock;
52+
}
53+
54+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.iluwatar.observer;
2+
3+
import org.junit.Test;
4+
5+
import java.util.function.Supplier;
6+
7+
import static org.mockito.Mockito.verify;
8+
import static org.mockito.Mockito.verifyNoMoreInteractions;
9+
import static org.mockito.Mockito.verifyZeroInteractions;
10+
11+
/**
12+
* Date: 12/27/15 - 11:44 AM
13+
*
14+
* @author Jeroen Meulemeester
15+
*/
16+
public abstract class WeatherObserverTest<O extends WeatherObserver> extends StdOutTest {
17+
18+
/**
19+
* The observer instance factory
20+
*/
21+
private final Supplier<O> factory;
22+
23+
/**
24+
* The weather type currently tested
25+
*/
26+
private final WeatherType weather;
27+
28+
/**
29+
* The expected response from the observer
30+
*/
31+
private final String response;
32+
33+
/**
34+
* Create a new test instance using the given parameters
35+
*
36+
* @param weather The weather currently being tested
37+
* @param response The expected response from the observer
38+
* @param factory The factory, used to create an instance of the tested observer
39+
*/
40+
WeatherObserverTest(final WeatherType weather, final String response, final Supplier<O> factory) {
41+
this.weather = weather;
42+
this.response = response;
43+
this.factory = factory;
44+
}
45+
46+
/**
47+
* Verify if the weather has the expected influence on the observer
48+
*/
49+
@Test
50+
public void testObserver() {
51+
final O observer = this.factory.get();
52+
verifyZeroInteractions(getStdOutMock());
53+
54+
observer.update(this.weather);
55+
verify(getStdOutMock()).println(this.response);
56+
verifyNoMoreInteractions(getStdOutMock());
57+
}
58+
59+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.iluwatar.observer;
2+
3+
import org.junit.Test;
4+
import org.mockito.InOrder;
5+
6+
import static org.mockito.Mockito.inOrder;
7+
import static org.mockito.Mockito.mock;
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/27/15 - 11:08 AM
14+
*
15+
* @author Jeroen Meulemeester
16+
*/
17+
public class WeatherTest extends StdOutTest {
18+
19+
/**
20+
* Add a {@link WeatherObserver}, verify if it gets notified of a weather change, remove the
21+
* observer again and verify that there are no more notifications.
22+
*/
23+
@Test
24+
public void testAddRemoveObserver() {
25+
final WeatherObserver observer = mock(WeatherObserver.class);
26+
27+
final Weather weather = new Weather();
28+
weather.addObserver(observer);
29+
verifyZeroInteractions(observer);
30+
31+
weather.timePasses();
32+
verify(getStdOutMock()).println("The weather changed to rainy.");
33+
verify(observer).update(WeatherType.RAINY);
34+
35+
weather.removeObserver(observer);
36+
weather.timePasses();
37+
verify(getStdOutMock()).println("The weather changed to windy.");
38+
39+
verifyNoMoreInteractions(observer, getStdOutMock());
40+
}
41+
42+
/**
43+
* Verify if the weather passes in the order of the {@link WeatherType}s
44+
*/
45+
@Test
46+
public void testTimePasses() {
47+
final WeatherObserver observer = mock(WeatherObserver.class);
48+
final Weather weather = new Weather();
49+
weather.addObserver(observer);
50+
51+
final InOrder inOrder = inOrder(observer, getStdOutMock());
52+
final WeatherType[] weatherTypes = WeatherType.values();
53+
for (int i = 1; i < 20; i++) {
54+
weather.timePasses();
55+
inOrder.verify(observer).update(weatherTypes[i % weatherTypes.length]);
56+
}
57+
58+
verifyNoMoreInteractions(observer);
59+
}
60+
61+
}

0 commit comments

Comments
 (0)