diff --git a/observer/src/main/java/com/iluwatar/observer/generic/Observable.java b/observer/src/main/java/com/iluwatar/observer/generic/Observable.java index f3b3c7dbb..e764245b7 100644 --- a/observer/src/main/java/com/iluwatar/observer/generic/Observable.java +++ b/observer/src/main/java/com/iluwatar/observer/generic/Observable.java @@ -22,6 +22,10 @@ public abstract class Observable, O extends Observ this.observers.add(observer); } + public void removeObserver(O observer) { + this.observers.remove(observer); + } + /** * Notify observers */ diff --git a/observer/src/test/java/com/iluwatar/observer/StdOutTest.java b/observer/src/test/java/com/iluwatar/observer/StdOutTest.java index 013dd67f7..3ea0bb119 100644 --- a/observer/src/test/java/com/iluwatar/observer/StdOutTest.java +++ b/observer/src/test/java/com/iluwatar/observer/StdOutTest.java @@ -47,7 +47,7 @@ public abstract class StdOutTest { * * @return The stdOut print stream mock, renewed before each test */ - final PrintStream getStdOutMock() { + protected final PrintStream getStdOutMock() { return this.stdOutMock; } diff --git a/observer/src/test/java/com/iluwatar/observer/generic/GHobbitsTest.java b/observer/src/test/java/com/iluwatar/observer/generic/GHobbitsTest.java new file mode 100644 index 000000000..6e955cf54 --- /dev/null +++ b/observer/src/test/java/com/iluwatar/observer/generic/GHobbitsTest.java @@ -0,0 +1,41 @@ +package com.iluwatar.observer.generic; + +import com.iluwatar.observer.Hobbits; +import com.iluwatar.observer.WeatherObserverTest; +import com.iluwatar.observer.WeatherType; + +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * Date: 12/27/15 - 12:07 PM + * + * @author Jeroen Meulemeester + */ +@RunWith(Parameterized.class) +public class GHobbitsTest extends ObserverTest { + + @Parameterized.Parameters + public static Collection data() { + final ArrayList testData = new ArrayList<>(); + testData.add(new Object[]{WeatherType.SUNNY, "The happy hobbits bade in the warm sun."}); + testData.add(new Object[]{WeatherType.RAINY, "The hobbits look for cover from the rain."}); + testData.add(new Object[]{WeatherType.WINDY, "The hobbits hold their hats tightly in the windy weather."}); + testData.add(new Object[]{WeatherType.COLD, "The hobbits are shivering in the cold weather."}); + return testData; + } + + /** + * Create a new test with the given weather and expected response + * + * @param weather The weather that should be unleashed on the observer + * @param response The expected response from the observer + */ + public GHobbitsTest(final WeatherType weather, final String response) { + super(weather, response, GHobbits::new); + } + +} diff --git a/observer/src/test/java/com/iluwatar/observer/generic/GWeatherTest.java b/observer/src/test/java/com/iluwatar/observer/generic/GWeatherTest.java new file mode 100644 index 000000000..b7a538167 --- /dev/null +++ b/observer/src/test/java/com/iluwatar/observer/generic/GWeatherTest.java @@ -0,0 +1,65 @@ +package com.iluwatar.observer.generic; + +import com.iluwatar.observer.StdOutTest; +import com.iluwatar.observer.WeatherObserver; +import com.iluwatar.observer.WeatherType; + +import org.junit.Test; +import org.mockito.InOrder; + +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Date: 12/27/15 - 11:08 AM + * + * @author Jeroen Meulemeester + */ +public class GWeatherTest extends StdOutTest { + + /** + * Add a {@link WeatherObserver}, verify if it gets notified of a weather change, remove the + * observer again and verify that there are no more notifications. + */ + @Test + public void testAddRemoveObserver() { + final Race observer = mock(Race.class); + + final GWeather weather = new GWeather(); + weather.addObserver(observer); + verifyZeroInteractions(observer); + + weather.timePasses(); + verify(getStdOutMock()).println("The weather changed to rainy."); + verify(observer).update(weather, WeatherType.RAINY); + + weather.removeObserver(observer); + weather.timePasses(); + verify(getStdOutMock()).println("The weather changed to windy."); + + verifyNoMoreInteractions(observer, getStdOutMock()); + } + + /** + * Verify if the weather passes in the order of the {@link WeatherType}s + */ + @Test + public void testTimePasses() { + final Race observer = mock(Race.class); + final GWeather weather = new GWeather(); + weather.addObserver(observer); + + final InOrder inOrder = inOrder(observer, getStdOutMock()); + final WeatherType[] weatherTypes = WeatherType.values(); + for (int i = 1; i < 20; i++) { + weather.timePasses(); + inOrder.verify(observer).update(weather, weatherTypes[i % weatherTypes.length]); + } + + verifyNoMoreInteractions(observer); + } + +} \ No newline at end of file diff --git a/observer/src/test/java/com/iluwatar/observer/generic/ObserverTest.java b/observer/src/test/java/com/iluwatar/observer/generic/ObserverTest.java new file mode 100644 index 000000000..2e664bd58 --- /dev/null +++ b/observer/src/test/java/com/iluwatar/observer/generic/ObserverTest.java @@ -0,0 +1,62 @@ +package com.iluwatar.observer.generic; + +import com.iluwatar.observer.StdOutTest; +import com.iluwatar.observer.WeatherType; + +import org.junit.Test; + +import java.util.function.Supplier; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Date: 12/27/15 - 11:44 AM + * + * @author Jeroen Meulemeester + */ +public abstract class ObserverTest extends StdOutTest { + + /** + * The observer instance factory + */ + private final Supplier factory; + + /** + * The weather type currently tested + */ + private final WeatherType weather; + + /** + * The expected response from the observer + */ + private final String response; + + /** + * Create a new test instance using the given parameters + * + * @param weather The weather currently being tested + * @param response The expected response from the observer + * @param factory The factory, used to create an instance of the tested observer + */ + ObserverTest(final WeatherType weather, final String response, final Supplier factory) { + this.weather = weather; + this.response = response; + this.factory = factory; + } + + /** + * Verify if the weather has the expected influence on the observer + */ + @Test + public void testObserver() { + final O observer = this.factory.get(); + verifyZeroInteractions(getStdOutMock()); + + observer.update(null, this.weather); + verify(getStdOutMock()).println(this.response); + verifyNoMoreInteractions(getStdOutMock()); + } + +} \ No newline at end of file diff --git a/observer/src/test/java/com/iluwatar/observer/generic/OrcsTest.java b/observer/src/test/java/com/iluwatar/observer/generic/OrcsTest.java new file mode 100644 index 000000000..508380970 --- /dev/null +++ b/observer/src/test/java/com/iluwatar/observer/generic/OrcsTest.java @@ -0,0 +1,39 @@ +package com.iluwatar.observer.generic; + +import com.iluwatar.observer.WeatherType; + +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * Date: 12/27/15 - 12:07 PM + * + * @author Jeroen Meulemeester + */ +@RunWith(Parameterized.class) +public class OrcsTest extends ObserverTest { + + @Parameterized.Parameters + public static Collection data() { + final ArrayList testData = new ArrayList<>(); + testData.add(new Object[]{WeatherType.SUNNY, "The sun hurts the orcs' eyes."}); + testData.add(new Object[]{WeatherType.RAINY, "The orcs are dripping wet."}); + testData.add(new Object[]{WeatherType.WINDY, "The orc smell almost vanishes in the wind."}); + testData.add(new Object[]{WeatherType.COLD, "The orcs are freezing cold."}); + return testData; + } + + /** + * Create a new test with the given weather and expected response + * + * @param weather The weather that should be unleashed on the observer + * @param response The expected response from the observer + */ + public OrcsTest(final WeatherType weather, final String response) { + super(weather, response, GOrcs::new); + } + +}