From b4dcec45eff608e4430445c2c0298d912e149170 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Tue, 22 Dec 2015 22:30:25 +0100 Subject: [PATCH 01/26] Added tests for multiton pattern --- .../com/iluwatar/multiton/NazgulTest.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 multiton/src/test/java/com/iluwatar/multiton/NazgulTest.java diff --git a/multiton/src/test/java/com/iluwatar/multiton/NazgulTest.java b/multiton/src/test/java/com/iluwatar/multiton/NazgulTest.java new file mode 100644 index 00000000..923f76b1 --- /dev/null +++ b/multiton/src/test/java/com/iluwatar/multiton/NazgulTest.java @@ -0,0 +1,29 @@ +package com.iluwatar.multiton; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; + +/** + * Date: 12/22/15 - 22:28 AM + * + * @author Jeroen Meulemeester + */ +public class NazgulTest { + + /** + * Verify if {@link Nazgul#getInstance(NazgulName)} returns the correct Nazgul multiton instance + */ + @Test + public void testGetInstance() { + for (final NazgulName name : NazgulName.values()) { + final Nazgul nazgul = Nazgul.getInstance(name); + assertNotNull(nazgul); + assertSame(nazgul, Nazgul.getInstance(name)); + assertEquals(name, nazgul.getName()); + } + } + +} From 8f6f171a3f5a17b865114cb72028b0811192737a Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sat, 26 Dec 2015 23:53:07 +0100 Subject: [PATCH 02/26] Added tests for null-object pattern --- null-object/pom.xml | 5 + .../com/iluwatar/nullobject/NullNodeTest.java | 43 ++++++++ .../com/iluwatar/nullobject/StdOutTest.java | 54 ++++++++++ .../com/iluwatar/nullobject/TreeTest.java | 101 ++++++++++++++++++ 4 files changed, 203 insertions(+) create mode 100644 null-object/src/test/java/com/iluwatar/nullobject/NullNodeTest.java create mode 100644 null-object/src/test/java/com/iluwatar/nullobject/StdOutTest.java create mode 100644 null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java diff --git a/null-object/pom.xml b/null-object/pom.xml index 1ffb5732..cae76c5c 100644 --- a/null-object/pom.xml +++ b/null-object/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/null-object/src/test/java/com/iluwatar/nullobject/NullNodeTest.java b/null-object/src/test/java/com/iluwatar/nullobject/NullNodeTest.java new file mode 100644 index 00000000..2bb9a1b4 --- /dev/null +++ b/null-object/src/test/java/com/iluwatar/nullobject/NullNodeTest.java @@ -0,0 +1,43 @@ +package com.iluwatar.nullobject; + +import org.junit.Test; +import org.mockito.Mockito; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +/** + * Date: 12/26/15 - 11:47 PM + * + * @author Jeroen Meulemeester + */ +public class NullNodeTest extends StdOutTest { + + /** + * Verify if {@link NullNode#getInstance()} actually returns the same object instance + */ + @Test + public void testGetInstance() { + final NullNode instance = NullNode.getInstance(); + assertNotNull(instance); + assertSame(instance, NullNode.getInstance()); + } + + @Test + public void testFields() { + final NullNode node = NullNode.getInstance(); + assertEquals(0, node.getTreeSize()); + assertNull(node.getName()); + assertNull(node.getLeft()); + assertNull(node.getRight()); + } + + @Test + public void testWalk() throws Exception { + NullNode.getInstance().walk(); + Mockito.verifyZeroInteractions(getStdOutMock()); + } + +} \ No newline at end of file diff --git a/null-object/src/test/java/com/iluwatar/nullobject/StdOutTest.java b/null-object/src/test/java/com/iluwatar/nullobject/StdOutTest.java new file mode 100644 index 00000000..5a9bae16 --- /dev/null +++ b/null-object/src/test/java/com/iluwatar/nullobject/StdOutTest.java @@ -0,0 +1,54 @@ +package com.iluwatar.nullobject; + +import org.junit.After; +import org.junit.Before; + +import java.io.PrintStream; + +import static org.mockito.Mockito.mock; + +/** + * Date: 12/10/15 - 8:37 PM + * + * @author Jeroen Meulemeester + */ +public abstract class StdOutTest { + + /** + * The mocked standard out {@link PrintStream}, required since walking through the tree has no + * influence on any other accessible object, except for writing to std-out using {@link + * System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Get the mocked stdOut {@link PrintStream} + * + * @return The stdOut print stream mock, renewed before each test + */ + final PrintStream getStdOutMock() { + return this.stdOutMock; + } + +} diff --git a/null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java b/null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java new file mode 100644 index 00000000..3599dd4c --- /dev/null +++ b/null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java @@ -0,0 +1,101 @@ +package com.iluwatar.nullobject; + +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mockito; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; + +/** + * Date: 12/26/15 - 11:44 PM + * + * @author Jeroen Meulemeester + */ +public class TreeTest extends StdOutTest { + + /** + * During the tests, the same tree structure will be used, shown below. End points will be + * terminated with the {@link NullNode} instance. + * + *
+   * root
+   * ├── level1_a
+   * │   ├── level2_a
+   * │   │   ├── level3_a
+   * │   │   └── level3_b
+   * │   └── level2_b
+   * └── level1_b
+   * 
+ */ + private static final Node TREE_ROOT; + + static { + final NodeImpl level1_b = new NodeImpl("level1_b", NullNode.getInstance(), NullNode.getInstance()); + final NodeImpl level2_b = new NodeImpl("level2_b", NullNode.getInstance(), NullNode.getInstance()); + final NodeImpl level3_a = new NodeImpl("level3_a", NullNode.getInstance(), NullNode.getInstance()); + final NodeImpl level3_b = new NodeImpl("level3_b", NullNode.getInstance(), NullNode.getInstance()); + final NodeImpl level2_a = new NodeImpl("level2_a", level3_a, level3_b); + final NodeImpl level1_a = new NodeImpl("level1_a", level2_a, level2_b); + TREE_ROOT = new NodeImpl("root", level1_a, level1_b); + } + + /** + * Verify the number of items in the tree. The root has 6 children so we expect a {@link + * Node#getTreeSize()} of 7 {@link Node}s in total. + */ + @Test + public void testTreeSize() { + assertEquals(7, TREE_ROOT.getTreeSize()); + } + + /** + * Walk through the tree and verify if every item is handled + */ + @Test + public void testWalk() { + TREE_ROOT.walk(); + + final InOrder inOrder = Mockito.inOrder(getStdOutMock()); + inOrder.verify(getStdOutMock()).println("root"); + inOrder.verify(getStdOutMock()).println("level1_a"); + inOrder.verify(getStdOutMock()).println("level2_a"); + inOrder.verify(getStdOutMock()).println("level3_a"); + inOrder.verify(getStdOutMock()).println("level3_b"); + inOrder.verify(getStdOutMock()).println("level2_b"); + inOrder.verify(getStdOutMock()).println("level1_b"); + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testGetLeft() throws Exception { + final Node level1 = TREE_ROOT.getLeft(); + assertNotNull(level1); + assertEquals("level1_a", level1.getName()); + assertEquals(5, level1.getTreeSize()); + + final Node level2 = level1.getLeft(); + assertNotNull(level2); + assertEquals("level2_a", level2.getName()); + assertEquals(3, level2.getTreeSize()); + + final Node level3 = level2.getLeft(); + assertNotNull(level3); + assertEquals("level3_a", level3.getName()); + assertEquals(1, level3.getTreeSize()); + assertSame(NullNode.getInstance(), level3.getRight()); + assertSame(NullNode.getInstance(), level3.getLeft()); + } + + @Test + public void testGetRight() throws Exception { + final Node level1 = TREE_ROOT.getRight(); + assertNotNull(level1); + assertEquals("level1_b", level1.getName()); + assertEquals(1, level1.getTreeSize()); + assertSame(NullNode.getInstance(), level1.getRight()); + assertSame(NullNode.getInstance(), level1.getLeft()); + } + +} From 4c938ab8a5a3d99d09fee867f0cdbe17bd171c0c Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 27 Dec 2015 09:37:43 +0100 Subject: [PATCH 03/26] Added tests for object-pool pattern --- .../object/pool/OliphauntPoolTest.java | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 object-pool/src/test/java/com/iluwatar/object/pool/OliphauntPoolTest.java diff --git a/object-pool/src/test/java/com/iluwatar/object/pool/OliphauntPoolTest.java b/object-pool/src/test/java/com/iluwatar/object/pool/OliphauntPoolTest.java new file mode 100644 index 00000000..347e0b4c --- /dev/null +++ b/object-pool/src/test/java/com/iluwatar/object/pool/OliphauntPoolTest.java @@ -0,0 +1,99 @@ +package com.iluwatar.object.pool; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +/** + * Date: 12/27/15 - 1:05 AM + * + * @author Jeroen Meulemeester + */ +public class OliphauntPoolTest { + + /** + * Use the same object 100 times subsequently. This should not take much time since the heavy + * object instantiation is done only once. Verify if we get the same object each time. + */ + @Test(timeout = 5000) + public void testSubsequentCheckinCheckout() { + final OliphauntPool pool = new OliphauntPool(); + assertEquals(pool.toString(), "Pool available=0 inUse=0"); + + final Oliphaunt expectedOliphaunt = pool.checkOut(); + assertEquals(pool.toString(), "Pool available=0 inUse=1"); + + pool.checkIn(expectedOliphaunt); + assertEquals(pool.toString(), "Pool available=1 inUse=0"); + + for (int i = 0; i < 100; i++) { + final Oliphaunt oliphaunt = pool.checkOut(); + assertEquals(pool.toString(), "Pool available=0 inUse=1"); + assertSame(expectedOliphaunt, oliphaunt); + assertEquals(expectedOliphaunt.getId(), oliphaunt.getId()); + assertEquals(expectedOliphaunt.toString(), oliphaunt.toString()); + + pool.checkIn(oliphaunt); + assertEquals(pool.toString(), "Pool available=1 inUse=0"); + } + + } + + /** + * Use the same object 100 times subsequently. This should not take much time since the heavy + * object instantiation is done only once. Verify if we get the same object each time. + */ + @Test(timeout = 5000) + public void testConcurrentCheckinCheckout() { + final OliphauntPool pool = new OliphauntPool(); + assertEquals(pool.toString(), "Pool available=0 inUse=0"); + + final Oliphaunt firstOliphaunt = pool.checkOut(); + assertEquals(pool.toString(), "Pool available=0 inUse=1"); + + final Oliphaunt secondOliphaunt = pool.checkOut(); + assertEquals(pool.toString(), "Pool available=0 inUse=2"); + + assertNotSame(firstOliphaunt, secondOliphaunt); + assertEquals(firstOliphaunt.getId() + 1, secondOliphaunt.getId()); + + // After checking in the second, we should get the same when checking out a new oliphaunt ... + pool.checkIn(secondOliphaunt); + assertEquals(pool.toString(), "Pool available=1 inUse=1"); + + final Oliphaunt oliphaunt3 = pool.checkOut(); + assertEquals(pool.toString(), "Pool available=0 inUse=2"); + assertSame(secondOliphaunt, oliphaunt3); + + // ... and the same applies for the first one + pool.checkIn(firstOliphaunt); + assertEquals(pool.toString(), "Pool available=1 inUse=1"); + + final Oliphaunt oliphaunt4 = pool.checkOut(); + assertEquals(pool.toString(), "Pool available=0 inUse=2"); + assertSame(firstOliphaunt, oliphaunt4); + + // When both oliphaunt return to the pool, we should still get the same instances + pool.checkIn(firstOliphaunt); + assertEquals(pool.toString(), "Pool available=1 inUse=1"); + + pool.checkIn(secondOliphaunt); + assertEquals(pool.toString(), "Pool available=2 inUse=0"); + + // The order of the returned instances is not determined, so just put them in a list + // and verify if both expected instances are in there. + final List oliphaunts = Arrays.asList(pool.checkOut(), pool.checkOut()); + assertEquals(pool.toString(), "Pool available=0 inUse=2"); + assertTrue(oliphaunts.contains(firstOliphaunt)); + assertTrue(oliphaunts.contains(secondOliphaunt)); + + } + + +} \ No newline at end of file From 3e20a2afa8eca027f3a04f2714974a373a06b48b Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 27 Dec 2015 13:26:15 +0100 Subject: [PATCH 04/26] Added tests for observer pattern --- observer/pom.xml | 5 ++ .../com/iluwatar/observer/HobbitsTest.java | 37 +++++++++++ .../java/com/iluwatar/observer/OrcsTest.java | 37 +++++++++++ .../com/iluwatar/observer/StdOutTest.java | 54 ++++++++++++++++ .../observer/WeatherObserverTest.java | 59 ++++++++++++++++++ .../com/iluwatar/observer/WeatherTest.java | 61 +++++++++++++++++++ 6 files changed, 253 insertions(+) create mode 100644 observer/src/test/java/com/iluwatar/observer/HobbitsTest.java create mode 100644 observer/src/test/java/com/iluwatar/observer/OrcsTest.java create mode 100644 observer/src/test/java/com/iluwatar/observer/StdOutTest.java create mode 100644 observer/src/test/java/com/iluwatar/observer/WeatherObserverTest.java create mode 100644 observer/src/test/java/com/iluwatar/observer/WeatherTest.java diff --git a/observer/pom.xml b/observer/pom.xml index 681c1957..629c0784 100644 --- a/observer/pom.xml +++ b/observer/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/observer/src/test/java/com/iluwatar/observer/HobbitsTest.java b/observer/src/test/java/com/iluwatar/observer/HobbitsTest.java new file mode 100644 index 00000000..3571ced6 --- /dev/null +++ b/observer/src/test/java/com/iluwatar/observer/HobbitsTest.java @@ -0,0 +1,37 @@ +package com.iluwatar.observer; + +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 HobbitsTest extends WeatherObserverTest { + + @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 HobbitsTest(final WeatherType weather, final String response) { + super(weather, response, Hobbits::new); + } + +} diff --git a/observer/src/test/java/com/iluwatar/observer/OrcsTest.java b/observer/src/test/java/com/iluwatar/observer/OrcsTest.java new file mode 100644 index 00000000..a59288ab --- /dev/null +++ b/observer/src/test/java/com/iluwatar/observer/OrcsTest.java @@ -0,0 +1,37 @@ +package com.iluwatar.observer; + +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 WeatherObserverTest { + + @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, Orcs::new); + } + +} diff --git a/observer/src/test/java/com/iluwatar/observer/StdOutTest.java b/observer/src/test/java/com/iluwatar/observer/StdOutTest.java new file mode 100644 index 00000000..013dd67f --- /dev/null +++ b/observer/src/test/java/com/iluwatar/observer/StdOutTest.java @@ -0,0 +1,54 @@ +package com.iluwatar.observer; + +import org.junit.After; +import org.junit.Before; + +import java.io.PrintStream; + +import static org.mockito.Mockito.mock; + +/** + * Date: 12/27/15 - 12:16 PM + * + * @author Jeroen Meulemeester + */ +public abstract class StdOutTest { + + /** + * The mocked standard out {@link PrintStream}, required since changes in the weather doesn't has + * any influence on any other accessible objects, except for writing to std-out using {@link + * System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Get the mocked stdOut {@link PrintStream} + * + * @return The stdOut print stream mock, renewed before each test + */ + final PrintStream getStdOutMock() { + return this.stdOutMock; + } + +} diff --git a/observer/src/test/java/com/iluwatar/observer/WeatherObserverTest.java b/observer/src/test/java/com/iluwatar/observer/WeatherObserverTest.java new file mode 100644 index 00000000..e4d6a443 --- /dev/null +++ b/observer/src/test/java/com/iluwatar/observer/WeatherObserverTest.java @@ -0,0 +1,59 @@ +package com.iluwatar.observer; + +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 WeatherObserverTest 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 + */ + WeatherObserverTest(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(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/WeatherTest.java b/observer/src/test/java/com/iluwatar/observer/WeatherTest.java new file mode 100644 index 00000000..a195be52 --- /dev/null +++ b/observer/src/test/java/com/iluwatar/observer/WeatherTest.java @@ -0,0 +1,61 @@ +package com.iluwatar.observer; + +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 WeatherTest 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 WeatherObserver observer = mock(WeatherObserver.class); + + final Weather weather = new Weather(); + weather.addObserver(observer); + verifyZeroInteractions(observer); + + weather.timePasses(); + verify(getStdOutMock()).println("The weather changed to rainy."); + verify(observer).update(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 WeatherObserver observer = mock(WeatherObserver.class); + final Weather weather = new Weather(); + 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(weatherTypes[i % weatherTypes.length]); + } + + verifyNoMoreInteractions(observer); + } + +} \ No newline at end of file From b3d1c2b2eddef78ca3b45457c21f358d046be792 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 27 Dec 2015 14:13:23 +0100 Subject: [PATCH 05/26] Added tests for generic observer pattern --- .../iluwatar/observer/generic/Observable.java | 4 ++ .../com/iluwatar/observer/StdOutTest.java | 2 +- .../observer/generic/GHobbitsTest.java | 41 ++++++++++++ .../observer/generic/GWeatherTest.java | 65 +++++++++++++++++++ .../observer/generic/ObserverTest.java | 62 ++++++++++++++++++ .../iluwatar/observer/generic/OrcsTest.java | 39 +++++++++++ 6 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 observer/src/test/java/com/iluwatar/observer/generic/GHobbitsTest.java create mode 100644 observer/src/test/java/com/iluwatar/observer/generic/GWeatherTest.java create mode 100644 observer/src/test/java/com/iluwatar/observer/generic/ObserverTest.java create mode 100644 observer/src/test/java/com/iluwatar/observer/generic/OrcsTest.java 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 f3b3c7db..e764245b 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 void addObserver(O observer) { 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 013dd67f..3ea0bb11 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 void tearDown() { * * @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 00000000..6e955cf5 --- /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 00000000..b7a53816 --- /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 00000000..2e664bd5 --- /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 00000000..50838097 --- /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); + } + +} From 47e1cd710c54d26fff8cc05c4e5f261a9c91effc Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 27 Dec 2015 22:42:39 +0100 Subject: [PATCH 06/26] Added tests for poison-pull pattern --- poison-pill/pom.xml | 5 ++ .../iluwatar/poison/pill/ConsumerTest.java | 56 ++++++++++++++++ .../poison/pill/PoisonMessageTest.java | 40 ++++++++++++ .../iluwatar/poison/pill/ProducerTest.java | 64 +++++++++++++++++++ .../poison/pill/SimpleMessageTest.java | 40 ++++++++++++ .../com/iluwatar/poison/pill/StdOutTest.java | 53 +++++++++++++++ 6 files changed, 258 insertions(+) create mode 100644 poison-pill/src/test/java/com/iluwatar/poison/pill/ConsumerTest.java create mode 100644 poison-pill/src/test/java/com/iluwatar/poison/pill/PoisonMessageTest.java create mode 100644 poison-pill/src/test/java/com/iluwatar/poison/pill/ProducerTest.java create mode 100644 poison-pill/src/test/java/com/iluwatar/poison/pill/SimpleMessageTest.java create mode 100644 poison-pill/src/test/java/com/iluwatar/poison/pill/StdOutTest.java diff --git a/poison-pill/pom.xml b/poison-pill/pom.xml index 0d7689b6..d4852869 100644 --- a/poison-pill/pom.xml +++ b/poison-pill/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/poison-pill/src/test/java/com/iluwatar/poison/pill/ConsumerTest.java b/poison-pill/src/test/java/com/iluwatar/poison/pill/ConsumerTest.java new file mode 100644 index 00000000..1c92f10d --- /dev/null +++ b/poison-pill/src/test/java/com/iluwatar/poison/pill/ConsumerTest.java @@ -0,0 +1,56 @@ +package com.iluwatar.poison.pill; + +import org.junit.Test; +import org.mockito.InOrder; + +import java.time.LocalDateTime; + +import static org.mockito.Mockito.inOrder; + +/** + * Date: 12/27/15 - 9:45 PM + * + * @author Jeroen Meulemeester + */ +public class ConsumerTest extends StdOutTest { + + @Test + public void testConsume() throws Exception { + final Message[] messages = new Message[]{ + createMessage("you", "Hello!"), + createMessage("me", "Hi!"), + Message.POISON_PILL, + createMessage("late_for_the_party", "Hello? Anyone here?"), + }; + + final MessageQueue queue = new SimpleMessageQueue(messages.length); + for (final Message message : messages) { + queue.put(message); + } + + new Consumer("NSA", queue).consume(); + + final InOrder inOrder = inOrder(getStdOutMock()); + inOrder.verify(getStdOutMock()).println("Message [Hello!] from [you] received by [NSA]"); + inOrder.verify(getStdOutMock()).println("Message [Hi!] from [me] received by [NSA]"); + inOrder.verify(getStdOutMock()).println("Consumer NSA receive request to terminate."); + inOrder.verifyNoMoreInteractions(); + + } + + /** + * Create a new message from the given sender with the given message body + * + * @param sender The sender's name + * @param message The message body + * @return The message instance + */ + private static Message createMessage(final String sender, final String message) { + final SimpleMessage msg = new SimpleMessage(); + msg.addHeader(Message.Headers.SENDER, sender); + msg.addHeader(Message.Headers.DATE, LocalDateTime.now().toString()); + msg.setBody(message); + return msg; + } + +} \ No newline at end of file diff --git a/poison-pill/src/test/java/com/iluwatar/poison/pill/PoisonMessageTest.java b/poison-pill/src/test/java/com/iluwatar/poison/pill/PoisonMessageTest.java new file mode 100644 index 00000000..9fb733aa --- /dev/null +++ b/poison-pill/src/test/java/com/iluwatar/poison/pill/PoisonMessageTest.java @@ -0,0 +1,40 @@ +package com.iluwatar.poison.pill; + +import org.junit.Test; + +import static com.iluwatar.poison.pill.Message.Headers; +import static com.iluwatar.poison.pill.Message.POISON_PILL; + +/** + * Date: 12/27/15 - 10:30 PM + * + * @author Jeroen Meulemeester + */ +public class PoisonMessageTest { + + @Test(expected = UnsupportedOperationException.class) + public void testAddHeader() throws Exception { + POISON_PILL.addHeader(Headers.SENDER, "sender"); + } + + @Test(expected = UnsupportedOperationException.class) + public void testGetHeader() throws Exception { + POISON_PILL.getHeader(Headers.SENDER); + } + + @Test(expected = UnsupportedOperationException.class) + public void testGetHeaders() throws Exception { + POISON_PILL.getHeaders(); + } + + @Test(expected = UnsupportedOperationException.class) + public void testSetBody() throws Exception { + POISON_PILL.setBody("Test message."); + } + + @Test(expected = UnsupportedOperationException.class) + public void testGetBody() throws Exception { + POISON_PILL.getBody(); + } + +} diff --git a/poison-pill/src/test/java/com/iluwatar/poison/pill/ProducerTest.java b/poison-pill/src/test/java/com/iluwatar/poison/pill/ProducerTest.java new file mode 100644 index 00000000..103020e4 --- /dev/null +++ b/poison-pill/src/test/java/com/iluwatar/poison/pill/ProducerTest.java @@ -0,0 +1,64 @@ +package com.iluwatar.poison.pill; + +import org.junit.Test; +import org.mockito.ArgumentCaptor; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; +import static org.mockito.Matchers.eq; +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 - 10:32 PM + * + * @author Jeroen Meulemeester + */ +public class ProducerTest { + + @Test + public void testSend() throws Exception { + final MqPublishPoint publishPoint = mock(MqPublishPoint.class); + final Producer producer = new Producer("producer", publishPoint); + verifyZeroInteractions(publishPoint); + + producer.send("Hello!"); + + final ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(Message.class); + verify(publishPoint).put(messageCaptor.capture()); + + final Message message = messageCaptor.getValue(); + assertNotNull(message); + assertEquals("producer", message.getHeader(Message.Headers.SENDER)); + assertNotNull(message.getHeader(Message.Headers.DATE)); + assertEquals("Hello!", message.getBody()); + + verifyNoMoreInteractions(publishPoint); + } + + @Test + public void testStop() throws Exception { + final MqPublishPoint publishPoint = mock(MqPublishPoint.class); + final Producer producer = new Producer("producer", publishPoint); + verifyZeroInteractions(publishPoint); + + producer.stop(); + verify(publishPoint).put(eq(Message.POISON_PILL)); + + try { + producer.send("Hello!"); + fail("Expected 'IllegalStateException' at this point, since the producer has stopped!"); + } catch (IllegalStateException e) { + assertNotNull(e); + assertNotNull(e.getMessage()); + assertEquals("Producer Hello! was stopped and fail to deliver requested message [producer].", + e.getMessage()); + } + + verifyNoMoreInteractions(publishPoint); + } + +} diff --git a/poison-pill/src/test/java/com/iluwatar/poison/pill/SimpleMessageTest.java b/poison-pill/src/test/java/com/iluwatar/poison/pill/SimpleMessageTest.java new file mode 100644 index 00000000..f5c348e2 --- /dev/null +++ b/poison-pill/src/test/java/com/iluwatar/poison/pill/SimpleMessageTest.java @@ -0,0 +1,40 @@ +package com.iluwatar.poison.pill; + +import org.junit.Test; + +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Date: 12/27/15 - 10:25 PM + * + * @author Jeroen Meulemeester + */ +public class SimpleMessageTest { + + @Test + public void testGetHeaders() { + final SimpleMessage message = new SimpleMessage(); + assertNotNull(message.getHeaders()); + assertTrue(message.getHeaders().isEmpty()); + + final String senderName = "test"; + message.addHeader(Message.Headers.SENDER, senderName); + assertNotNull(message.getHeaders()); + assertFalse(message.getHeaders().isEmpty()); + assertEquals(senderName, message.getHeaders().get(Message.Headers.SENDER)); + } + + @Test(expected = UnsupportedOperationException.class) + public void testUnModifiableHeaders() { + final SimpleMessage message = new SimpleMessage(); + final Map headers = message.getHeaders(); + headers.put(Message.Headers.SENDER, "test"); + } + + +} \ No newline at end of file diff --git a/poison-pill/src/test/java/com/iluwatar/poison/pill/StdOutTest.java b/poison-pill/src/test/java/com/iluwatar/poison/pill/StdOutTest.java new file mode 100644 index 00000000..9c533b5c --- /dev/null +++ b/poison-pill/src/test/java/com/iluwatar/poison/pill/StdOutTest.java @@ -0,0 +1,53 @@ +package com.iluwatar.poison.pill; + +import org.junit.After; +import org.junit.Before; + +import java.io.PrintStream; + +import static org.mockito.Mockito.mock; + +/** + * Date: 12/10/15 - 8:37 PM + * + * @author Jeroen Meulemeester + */ +public abstract class StdOutTest { + + /** + * The mocked standard out {@link PrintStream}, required since some actions don't have any + * influence on accessible objects, except for writing to std-out using {@link System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Get the mocked stdOut {@link PrintStream} + * + * @return The stdOut print stream mock, renewed before each test + */ + final PrintStream getStdOutMock() { + return this.stdOutMock; + } + +} From 42a1dc69ca3bfe336c6d01f73259c8a9bd38bb59 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Sun, 27 Dec 2015 22:58:39 +0100 Subject: [PATCH 07/26] Added tests for private-class-data pattern --- private-class-data/pom.xml | 5 ++ .../privateclassdata/ImmutableStewTest.java | 52 ++++++++++++++++++ .../iluwatar/privateclassdata/StdOutTest.java | 53 +++++++++++++++++++ .../iluwatar/privateclassdata/StewTest.java | 33 ++++++++++++ 4 files changed, 143 insertions(+) create mode 100644 private-class-data/src/test/java/com/iluwatar/privateclassdata/ImmutableStewTest.java create mode 100644 private-class-data/src/test/java/com/iluwatar/privateclassdata/StdOutTest.java create mode 100644 private-class-data/src/test/java/com/iluwatar/privateclassdata/StewTest.java diff --git a/private-class-data/pom.xml b/private-class-data/pom.xml index cced926f..856934ac 100644 --- a/private-class-data/pom.xml +++ b/private-class-data/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/private-class-data/src/test/java/com/iluwatar/privateclassdata/ImmutableStewTest.java b/private-class-data/src/test/java/com/iluwatar/privateclassdata/ImmutableStewTest.java new file mode 100644 index 00000000..da5335b0 --- /dev/null +++ b/private-class-data/src/test/java/com/iluwatar/privateclassdata/ImmutableStewTest.java @@ -0,0 +1,52 @@ +package com.iluwatar.privateclassdata; + +import org.junit.Test; +import org.mockito.InOrder; + +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.verify; + +/** + * Date: 12/27/15 - 10:46 PM + * + * @author Jeroen Meulemeester + */ +public class ImmutableStewTest extends StdOutTest { + + /** + * Verify if mixing the stew doesn't change the internal state + */ + @Test + public void testMix() { + final Stew stew = new Stew(1, 2, 3, 4); + final String message = "Mixing the stew we find: 1 potatoes, 2 carrots, 3 meat and 4 peppers"; + + final InOrder inOrder = inOrder(getStdOutMock()); + for (int i = 0; i < 20; i++) { + stew.mix(); + inOrder.verify(getStdOutMock()).println(message); + } + + inOrder.verifyNoMoreInteractions(); + } + + /** + * Verify if tasting the stew actually removes one of each ingredient + */ + @Test + public void testDrink() { + final Stew stew = new Stew(1, 2, 3, 4); + stew.mix(); + + verify(getStdOutMock()) + .println("Mixing the stew we find: 1 potatoes, 2 carrots, 3 meat and 4 peppers"); + + stew.taste(); + verify(getStdOutMock()).println("Tasting the stew"); + + stew.mix(); + verify(getStdOutMock()) + .println("Mixing the stew we find: 0 potatoes, 1 carrots, 2 meat and 3 peppers"); + + } +} \ No newline at end of file diff --git a/private-class-data/src/test/java/com/iluwatar/privateclassdata/StdOutTest.java b/private-class-data/src/test/java/com/iluwatar/privateclassdata/StdOutTest.java new file mode 100644 index 00000000..91904c31 --- /dev/null +++ b/private-class-data/src/test/java/com/iluwatar/privateclassdata/StdOutTest.java @@ -0,0 +1,53 @@ +package com.iluwatar.privateclassdata; + +import org.junit.After; +import org.junit.Before; + +import java.io.PrintStream; + +import static org.mockito.Mockito.mock; + +/** + * Date: 12/10/15 - 8:37 PM + * + * @author Jeroen Meulemeester + */ +public abstract class StdOutTest { + + /** + * The mocked standard out {@link PrintStream}, required since some actions don't have any + * influence on accessible objects, except for writing to std-out using {@link System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Get the mocked stdOut {@link PrintStream} + * + * @return The stdOut print stream mock, renewed before each test + */ + final PrintStream getStdOutMock() { + return this.stdOutMock; + } + +} diff --git a/private-class-data/src/test/java/com/iluwatar/privateclassdata/StewTest.java b/private-class-data/src/test/java/com/iluwatar/privateclassdata/StewTest.java new file mode 100644 index 00000000..d6b67a35 --- /dev/null +++ b/private-class-data/src/test/java/com/iluwatar/privateclassdata/StewTest.java @@ -0,0 +1,33 @@ +package com.iluwatar.privateclassdata; + +import org.junit.Test; +import org.mockito.InOrder; + +import static org.mockito.Mockito.inOrder; + +/** + * Date: 12/27/15 - 10:46 PM + * + * @author Jeroen Meulemeester + */ +public class StewTest extends StdOutTest { + + /** + * Verify if mixing the stew doesn't change the internal state + */ + @Test + public void testMix() { + final ImmutableStew stew = new ImmutableStew(1, 2, 3, 4); + final String expectedMessage = "Mixing the immutable stew we find: 1 potatoes, " + + "2 carrots, 3 meat and 4 peppers"; + + final InOrder inOrder = inOrder(getStdOutMock()); + for (int i = 0; i < 20; i++) { + stew.mix(); + inOrder.verify(getStdOutMock()).println(expectedMessage); + } + + inOrder.verifyNoMoreInteractions(); + } + +} \ No newline at end of file From dca68511e80d3c6604445cbf680c0ec688908624 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Mon, 28 Dec 2015 00:16:43 +0100 Subject: [PATCH 08/26] Added tests for producer-consumer pattern --- producer-consumer/pom.xml | 5 ++ .../producer/consumer/ConsumerTest.java | 39 ++++++++++++++ .../producer/consumer/ProducerTest.java | 28 ++++++++++ .../producer/consumer/StdOutTest.java | 53 +++++++++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 producer-consumer/src/test/java/com/iluwatar/producer/consumer/ConsumerTest.java create mode 100644 producer-consumer/src/test/java/com/iluwatar/producer/consumer/ProducerTest.java create mode 100644 producer-consumer/src/test/java/com/iluwatar/producer/consumer/StdOutTest.java diff --git a/producer-consumer/pom.xml b/producer-consumer/pom.xml index 518ef94d..5f18a849 100644 --- a/producer-consumer/pom.xml +++ b/producer-consumer/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ConsumerTest.java b/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ConsumerTest.java new file mode 100644 index 00000000..e7b60a06 --- /dev/null +++ b/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ConsumerTest.java @@ -0,0 +1,39 @@ +package com.iluwatar.producer.consumer; + +import org.junit.Test; +import org.mockito.InOrder; + +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.spy; + +/** + * Date: 12/27/15 - 11:01 PM + * + * @author Jeroen Meulemeester + */ +public class ConsumerTest extends StdOutTest { + + private static final int ITEM_COUNT = 5; + + @Test + public void testConsume() throws Exception { + final ItemQueue queue = spy(new ItemQueue()); + for (int id = 0; id < ITEM_COUNT; id++) { + queue.put(new Item("producer", id)); + } + + reset(queue); // Don't count the preparation above as interactions with the queue + final Consumer consumer = new Consumer("consumer", queue); + + final InOrder inOrder = inOrder(getStdOutMock()); + for (int id = 0; id < ITEM_COUNT; id++) { + consumer.consume(); + inOrder.verify(getStdOutMock()) + .println("Consumer [consumer] consume item [" + id + "] produced by [producer]"); + } + + inOrder.verifyNoMoreInteractions(); + } + +} diff --git a/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ProducerTest.java b/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ProducerTest.java new file mode 100644 index 00000000..0605879d --- /dev/null +++ b/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ProducerTest.java @@ -0,0 +1,28 @@ +package com.iluwatar.producer.consumer; + +import org.junit.Test; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +/** + * Date: 12/28/15 - 12:12 AM + * + * @author Jeroen Meulemeester + */ +public class ProducerTest { + + @Test(timeout = 6000) + public void testProduce() throws Exception { + final ItemQueue queue = mock(ItemQueue.class); + final Producer producer = new Producer("producer", queue); + + producer.produce(); + verify(queue).put(any(Item.class)); + + verifyNoMoreInteractions(queue); + } + +} \ No newline at end of file diff --git a/producer-consumer/src/test/java/com/iluwatar/producer/consumer/StdOutTest.java b/producer-consumer/src/test/java/com/iluwatar/producer/consumer/StdOutTest.java new file mode 100644 index 00000000..85d8fe6c --- /dev/null +++ b/producer-consumer/src/test/java/com/iluwatar/producer/consumer/StdOutTest.java @@ -0,0 +1,53 @@ +package com.iluwatar.producer.consumer; + +import org.junit.After; +import org.junit.Before; + +import java.io.PrintStream; + +import static org.mockito.Mockito.mock; + +/** + * Date: 12/10/15 - 8:37 PM + * + * @author Jeroen Meulemeester + */ +public abstract class StdOutTest { + + /** + * The mocked standard out {@link PrintStream}, required since some actions don't have any + * influence on accessible objects, except for writing to std-out using {@link System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Get the mocked stdOut {@link PrintStream} + * + * @return The stdOut print stream mock, renewed before each test + */ + final PrintStream getStdOutMock() { + return this.stdOutMock; + } + +} From a3b12659218d81f64f08eb670218500cca0cc31c Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Mon, 28 Dec 2015 20:21:20 +0100 Subject: [PATCH 09/26] Added tests for property pattern --- .../com/iluwatar/property/CharacterTest.java | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 property/src/test/java/com/iluwatar/property/CharacterTest.java diff --git a/property/src/test/java/com/iluwatar/property/CharacterTest.java b/property/src/test/java/com/iluwatar/property/CharacterTest.java new file mode 100644 index 00000000..6d9a7a14 --- /dev/null +++ b/property/src/test/java/com/iluwatar/property/CharacterTest.java @@ -0,0 +1,103 @@ +package com.iluwatar.property; + +import org.junit.Test; + +import static com.iluwatar.property.Character.Type; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Date: 12/28/15 - 7:46 PM + * + * @author Jeroen Meulemeester + */ +public class CharacterTest { + + @Test + public void testPrototypeStats() throws Exception { + final Character prototype = new Character(); + + for (final Stats stat : Stats.values()) { + assertFalse(prototype.has(stat)); + assertNull(prototype.get(stat)); + + final Integer expectedValue = stat.ordinal(); + prototype.set(stat, expectedValue); + assertTrue(prototype.has(stat)); + assertEquals(expectedValue, prototype.get(stat)); + + prototype.remove(stat); + assertFalse(prototype.has(stat)); + assertNull(prototype.get(stat)); + } + + } + + @Test + public void testCharacterStats() throws Exception { + final Character prototype = new Character(); + for (final Stats stat : Stats.values()) { + prototype.set(stat, stat.ordinal()); + } + + final Character mage = new Character(Type.MAGE, prototype); + for (final Stats stat : Stats.values()) { + final Integer expectedValue = stat.ordinal(); + assertTrue(mage.has(stat)); + assertEquals(expectedValue, mage.get(stat)); + } + } + + @Test + public void testToString() throws Exception { + final Character prototype = new Character(); + prototype.set(Stats.ARMOR, 1); + prototype.set(Stats.AGILITY, 2); + prototype.set(Stats.INTELLECT, 3); + assertEquals("Stats:\n - AGILITY:2\n - ARMOR:1\n - INTELLECT:3\n", prototype.toString()); + + final Character stupid = new Character(Type.ROGUE, prototype); + stupid.remove(Stats.INTELLECT); + assertEquals("Character type: ROGUE\nStats:\n - AGILITY:2\n - ARMOR:1\n", stupid.toString()); + + final Character weak = new Character("weak", prototype); + weak.remove(Stats.ARMOR); + assertEquals("Player: weak\nStats:\n - AGILITY:2\n - INTELLECT:3\n", weak.toString()); + + } + + @Test + public void testName() throws Exception { + final Character prototype = new Character(); + prototype.set(Stats.ARMOR, 1); + prototype.set(Stats.INTELLECT, 2); + assertNull(prototype.name()); + + final Character stupid = new Character(Type.ROGUE, prototype); + stupid.remove(Stats.INTELLECT); + assertNull(stupid.name()); + + final Character weak = new Character("weak", prototype); + weak.remove(Stats.ARMOR); + assertEquals("weak", weak.name()); + } + + @Test + public void testType() throws Exception { + final Character prototype = new Character(); + prototype.set(Stats.ARMOR, 1); + prototype.set(Stats.INTELLECT, 2); + assertNull(prototype.type()); + + final Character stupid = new Character(Type.ROGUE, prototype); + stupid.remove(Stats.INTELLECT); + assertEquals(Type.ROGUE, stupid.type()); + + final Character weak = new Character("weak", prototype); + weak.remove(Stats.ARMOR); + assertNull(weak.type()); + } + +} \ No newline at end of file From 9d4c3154b1affe369b804e49a10cd872e476c8cd Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Mon, 28 Dec 2015 21:01:25 +0100 Subject: [PATCH 10/26] Added tests for prototype pattern --- prototype/pom.xml | 5 ++ .../prototype/HeroFactoryImplTest.java | 39 +++++++++++ .../com/iluwatar/prototype/PrototypeTest.java | 66 +++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 prototype/src/test/java/com/iluwatar/prototype/HeroFactoryImplTest.java create mode 100644 prototype/src/test/java/com/iluwatar/prototype/PrototypeTest.java diff --git a/prototype/pom.xml b/prototype/pom.xml index 5e91880a..93b162b2 100644 --- a/prototype/pom.xml +++ b/prototype/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/prototype/src/test/java/com/iluwatar/prototype/HeroFactoryImplTest.java b/prototype/src/test/java/com/iluwatar/prototype/HeroFactoryImplTest.java new file mode 100644 index 00000000..e237b43b --- /dev/null +++ b/prototype/src/test/java/com/iluwatar/prototype/HeroFactoryImplTest.java @@ -0,0 +1,39 @@ +package com.iluwatar.prototype; + +import org.junit.Test; + +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +/** + * Date: 12/28/15 - 8:34 PM + * + * @author Jeroen Meulemeester + */ +public class HeroFactoryImplTest { + + @Test + public void testFactory() throws Exception { + final Mage mage = mock(Mage.class); + final Warlord warlord = mock(Warlord.class); + final Beast beast = mock(Beast.class); + + when(mage.clone()).thenThrow(CloneNotSupportedException.class); + when(warlord.clone()).thenThrow(CloneNotSupportedException.class); + when(beast.clone()).thenThrow(CloneNotSupportedException.class); + + final HeroFactoryImpl factory = new HeroFactoryImpl(mage, warlord, beast); + assertNull(factory.createMage()); + assertNull(factory.createWarlord()); + assertNull(factory.createBeast()); + + verify(mage).clone(); + verify(warlord).clone(); + verify(beast).clone(); + verifyNoMoreInteractions(mage, warlord, beast); + } + +} \ No newline at end of file diff --git a/prototype/src/test/java/com/iluwatar/prototype/PrototypeTest.java b/prototype/src/test/java/com/iluwatar/prototype/PrototypeTest.java new file mode 100644 index 00000000..3e3d8f88 --- /dev/null +++ b/prototype/src/test/java/com/iluwatar/prototype/PrototypeTest.java @@ -0,0 +1,66 @@ +package com.iluwatar.prototype; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Arrays; +import java.util.Collection; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; + +/** + * Date: 12/28/15 - 8:45 PM + * + * @author Jeroen Meulemeester + */ +@RunWith(Parameterized.class) +public class PrototypeTest

{ + + @Parameterized.Parameters + public static Collection data() { + return Arrays.asList( + new Object[]{new OrcBeast(), "Orcish wolf"}, + new Object[]{new OrcMage(), "Orcish mage"}, + new Object[]{new OrcWarlord(), "Orcish warlord"}, + new Object[]{new ElfBeast(), "Elven eagle"}, + new Object[]{new ElfMage(), "Elven mage"}, + new Object[]{new ElfWarlord(), "Elven warlord"} + ); + } + + /** + * The tested prototype instance + */ + private final Prototype testedPrototype; + + /** + * The expected {@link Prototype#toString()} value + */ + private final String expectedToString; + + /** + * Create a new test instance, using the given test object and expected value + * + * @param testedPrototype The tested prototype instance + * @param expectedToString The expected {@link Prototype#toString()} value + */ + public PrototypeTest(final Prototype testedPrototype, final String expectedToString) { + this.expectedToString = expectedToString; + this.testedPrototype = testedPrototype; + } + + @Test + public void testPrototype() throws Exception { + assertEquals(this.expectedToString, this.testedPrototype.toString()); + + final Object clone = this.testedPrototype.clone(); + assertNotNull(clone); + assertNotSame(clone, this.testedPrototype); + assertSame(this.testedPrototype.getClass(), clone.getClass()); + } + +} From 299d612b9b4a4a7d71235c660031d4b2e1987987 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Mon, 28 Dec 2015 21:28:12 +0100 Subject: [PATCH 11/26] Added tests for proxy pattern --- proxy/pom.xml | 5 ++ .../java/com/iluwatar/proxy/StdOutTest.java | 53 +++++++++++++++++++ .../java/com/iluwatar/proxy/WizardTest.java | 22 ++++++++ .../iluwatar/proxy/WizardTowerProxyTest.java | 38 +++++++++++++ .../com/iluwatar/proxy/WizardTowerTest.java | 38 +++++++++++++ 5 files changed, 156 insertions(+) create mode 100644 proxy/src/test/java/com/iluwatar/proxy/StdOutTest.java create mode 100644 proxy/src/test/java/com/iluwatar/proxy/WizardTest.java create mode 100644 proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java create mode 100644 proxy/src/test/java/com/iluwatar/proxy/WizardTowerTest.java diff --git a/proxy/pom.xml b/proxy/pom.xml index 3a662b37..77b6a04b 100644 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/proxy/src/test/java/com/iluwatar/proxy/StdOutTest.java b/proxy/src/test/java/com/iluwatar/proxy/StdOutTest.java new file mode 100644 index 00000000..a145b7b8 --- /dev/null +++ b/proxy/src/test/java/com/iluwatar/proxy/StdOutTest.java @@ -0,0 +1,53 @@ +package com.iluwatar.proxy; + +import org.junit.After; +import org.junit.Before; + +import java.io.PrintStream; + +import static org.mockito.Mockito.mock; + +/** + * Date: 12/10/15 - 8:37 PM + * + * @author Jeroen Meulemeester + */ +public abstract class StdOutTest { + + /** + * The mocked standard out {@link PrintStream}, required since some actions don't have any + * influence on accessible objects, except for writing to std-out using {@link System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Get the mocked stdOut {@link PrintStream} + * + * @return The stdOut print stream mock, renewed before each test + */ + final PrintStream getStdOutMock() { + return this.stdOutMock; + } + +} diff --git a/proxy/src/test/java/com/iluwatar/proxy/WizardTest.java b/proxy/src/test/java/com/iluwatar/proxy/WizardTest.java new file mode 100644 index 00000000..c1b9e6fe --- /dev/null +++ b/proxy/src/test/java/com/iluwatar/proxy/WizardTest.java @@ -0,0 +1,22 @@ +package com.iluwatar.proxy; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Date: 12/28/15 - 9:02 PM + * + * @author Jeroen Meulemeester + */ +public class WizardTest { + + @Test + public void testToString() throws Exception { + final String[] wizardNames = {"Gandalf", "Dumbledore", "Oz", "Merlin"}; + for (final String name : wizardNames) { + assertEquals(name, new Wizard(name).toString()); + } + } + +} \ No newline at end of file diff --git a/proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java b/proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java new file mode 100644 index 00000000..f4deb192 --- /dev/null +++ b/proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java @@ -0,0 +1,38 @@ +package com.iluwatar.proxy; + +import org.junit.Test; +import org.mockito.InOrder; + +import static org.mockito.Mockito.inOrder; + +/** + * Date: 12/28/15 - 9:18 PM + * + * @author Jeroen Meulemeester + */ +public class WizardTowerProxyTest extends StdOutTest { + + @Test + public void testEnter() throws Exception { + final Wizard[] wizards = new Wizard[]{ + new Wizard("Gandalf"), + new Wizard("Dumbledore"), + new Wizard("Oz"), + new Wizard("Merlin") + }; + + final WizardTowerProxy tower = new WizardTowerProxy(); + for (final Wizard wizard : wizards) { + tower.enter(wizard); + } + + final InOrder inOrder = inOrder(getStdOutMock()); + inOrder.verify(getStdOutMock()).println("Gandalf enters the tower."); + inOrder.verify(getStdOutMock()).println("Dumbledore enters the tower."); + inOrder.verify(getStdOutMock()).println("Oz enters the tower."); + inOrder.verify(getStdOutMock()).println("Merlin is not allowed to enter!"); + inOrder.verifyNoMoreInteractions(); + + } + +} \ No newline at end of file diff --git a/proxy/src/test/java/com/iluwatar/proxy/WizardTowerTest.java b/proxy/src/test/java/com/iluwatar/proxy/WizardTowerTest.java new file mode 100644 index 00000000..5ddb7dda --- /dev/null +++ b/proxy/src/test/java/com/iluwatar/proxy/WizardTowerTest.java @@ -0,0 +1,38 @@ +package com.iluwatar.proxy; + +import org.junit.Test; +import org.mockito.InOrder; + +import static org.mockito.Mockito.inOrder; + +/** + * Date: 12/28/15 - 9:18 PM + * + * @author Jeroen Meulemeester + */ +public class WizardTowerTest extends StdOutTest { + + @Test + public void testEnter() throws Exception { + final Wizard[] wizards = new Wizard[]{ + new Wizard("Gandalf"), + new Wizard("Dumbledore"), + new Wizard("Oz"), + new Wizard("Merlin") + }; + + final WizardTower tower = new WizardTower(); + for (final Wizard wizard : wizards) { + tower.enter(wizard); + } + + final InOrder inOrder = inOrder(getStdOutMock()); + inOrder.verify(getStdOutMock()).println("Gandalf enters the tower."); + inOrder.verify(getStdOutMock()).println("Dumbledore enters the tower."); + inOrder.verify(getStdOutMock()).println("Oz enters the tower."); + inOrder.verify(getStdOutMock()).println("Merlin enters the tower."); + inOrder.verifyNoMoreInteractions(); + + } + +} \ No newline at end of file From c72faeb67eb311e2ea3313ea8b3f70991e827608 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Mon, 28 Dec 2015 21:37:32 +0100 Subject: [PATCH 12/26] Added tests for resource-acquisition-is-initialization pattern --- .../pom.xml | 5 ++ .../is/initialization/ClosableTest.java | 27 ++++++++++ .../is/initialization/StdOutTest.java | 53 +++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/ClosableTest.java create mode 100644 resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/StdOutTest.java diff --git a/resource-acquisition-is-initialization/pom.xml b/resource-acquisition-is-initialization/pom.xml index 133c7f3c..ff6c3f8c 100644 --- a/resource-acquisition-is-initialization/pom.xml +++ b/resource-acquisition-is-initialization/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/ClosableTest.java b/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/ClosableTest.java new file mode 100644 index 00000000..423d0ab5 --- /dev/null +++ b/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/ClosableTest.java @@ -0,0 +1,27 @@ +package com.iluwatar.resource.acquisition.is.initialization; + +import org.junit.Test; +import org.mockito.InOrder; + +import static org.mockito.Mockito.inOrder; + +/** + * Date: 12/28/15 - 9:31 PM + * + * @author Jeroen Meulemeester + */ +public class ClosableTest extends StdOutTest { + + @Test + public void testOpenClose() throws Exception { + final InOrder inOrder = inOrder(getStdOutMock()); + try (final SlidingDoor door = new SlidingDoor(); final TreasureChest chest = new TreasureChest()) { + inOrder.verify(getStdOutMock()).println("Sliding door opens."); + inOrder.verify(getStdOutMock()).println("Treasure chest opens."); + } + inOrder.verify(getStdOutMock()).println("Treasure chest closes."); + inOrder.verify(getStdOutMock()).println("Sliding door closes."); + inOrder.verifyNoMoreInteractions(); + } + +} \ No newline at end of file diff --git a/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/StdOutTest.java b/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/StdOutTest.java new file mode 100644 index 00000000..2fdc09e2 --- /dev/null +++ b/resource-acquisition-is-initialization/src/test/java/com/iluwatar/resource/acquisition/is/initialization/StdOutTest.java @@ -0,0 +1,53 @@ +package com.iluwatar.resource.acquisition.is.initialization; + +import org.junit.After; +import org.junit.Before; + +import java.io.PrintStream; + +import static org.mockito.Mockito.mock; + +/** + * Date: 12/10/15 - 8:37 PM + * + * @author Jeroen Meulemeester + */ +public abstract class StdOutTest { + + /** + * The mocked standard out {@link PrintStream}, required since some actions don't have any + * influence on accessible objects, except for writing to std-out using {@link System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Get the mocked stdOut {@link PrintStream} + * + * @return The stdOut print stream mock, renewed before each test + */ + final PrintStream getStdOutMock() { + return this.stdOutMock; + } + +} From 52c483f1d0d6bc4bc9c04ef3b5584928ed7ef82f Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Mon, 28 Dec 2015 22:10:07 +0100 Subject: [PATCH 13/26] Added tests for servant pattern --- servant/pom.xml | 5 ++ .../java/com/iluwatar/servant/KingTest.java | 82 +++++++++++++++++++ .../java/com/iluwatar/servant/QueenTest.java | 46 +++++++++++ .../com/iluwatar/servant/ServantTest.java | 70 ++++++++++++++++ 4 files changed, 203 insertions(+) create mode 100644 servant/src/test/java/com/iluwatar/servant/KingTest.java create mode 100644 servant/src/test/java/com/iluwatar/servant/QueenTest.java create mode 100644 servant/src/test/java/com/iluwatar/servant/ServantTest.java diff --git a/servant/pom.xml b/servant/pom.xml index 19d58490..c49c9ffc 100644 --- a/servant/pom.xml +++ b/servant/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/servant/src/test/java/com/iluwatar/servant/KingTest.java b/servant/src/test/java/com/iluwatar/servant/KingTest.java new file mode 100644 index 00000000..3c0811bc --- /dev/null +++ b/servant/src/test/java/com/iluwatar/servant/KingTest.java @@ -0,0 +1,82 @@ +package com.iluwatar.servant; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Date: 12/28/15 - 9:40 PM + * + * @author Jeroen Meulemeester + */ +public class KingTest { + + @Test + public void testHungrySoberUncomplimentedKing() { + final King king = new King(); + king.changeMood(); + assertFalse(king.getMood()); + } + + @Test + public void testFedSoberUncomplimentedKing() { + final King king = new King(); + king.getFed(); + king.changeMood(); + assertFalse(king.getMood()); + } + + @Test + public void testHungryDrunkUncomplimentedKing() { + final King king = new King(); + king.getDrink(); + king.changeMood(); + assertFalse(king.getMood()); + } + + @Test + public void testHungrySoberComplimentedKing() { + final King king = new King(); + king.receiveCompliments(); + king.changeMood(); + assertFalse(king.getMood()); + } + + @Test + public void testFedDrunkUncomplimentedKing() { + final King king = new King(); + king.getFed(); + king.getDrink(); + king.changeMood(); + assertTrue(king.getMood()); + } + + @Test + public void testFedSoberComplimentedKing() { + final King king = new King(); + king.getFed(); + king.receiveCompliments(); + king.changeMood(); + assertFalse(king.getMood()); + } + + @Test + public void testFedDrunkComplimentedKing() { + final King king = new King(); + king.getFed(); + king.getDrink(); + king.receiveCompliments(); + king.changeMood(); + assertFalse(king.getMood()); + } + + @Test + public void testHungryDrunkComplimentedKing() { + final King king = new King(); + king.getDrink(); + king.receiveCompliments(); + king.changeMood(); + assertFalse(king.getMood()); + } + +} \ No newline at end of file diff --git a/servant/src/test/java/com/iluwatar/servant/QueenTest.java b/servant/src/test/java/com/iluwatar/servant/QueenTest.java new file mode 100644 index 00000000..d6f02774 --- /dev/null +++ b/servant/src/test/java/com/iluwatar/servant/QueenTest.java @@ -0,0 +1,46 @@ +package com.iluwatar.servant; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Date: 12/28/15 - 9:52 PM + * + * @author Jeroen Meulemeester + */ +public class QueenTest { + + @Test + public void testNotFlirtyUncomplemented() throws Exception { + final Queen queen = new Queen(); + queen.setFlirtiness(false); + queen.changeMood(); + assertFalse(queen.getMood()); + } + + @Test + public void testNotFlirtyComplemented() throws Exception { + final Queen queen = new Queen(); + queen.setFlirtiness(false); + queen.receiveCompliments(); + queen.changeMood(); + assertFalse(queen.getMood()); + } + + @Test + public void testFlirtyUncomplemented() throws Exception { + final Queen queen = new Queen(); + queen.changeMood(); + assertFalse(queen.getMood()); + } + + @Test + public void testFlirtyComplemented() throws Exception { + final Queen queen = new Queen(); + queen.receiveCompliments(); + queen.changeMood(); + assertTrue(queen.getMood()); + } + +} \ No newline at end of file diff --git a/servant/src/test/java/com/iluwatar/servant/ServantTest.java b/servant/src/test/java/com/iluwatar/servant/ServantTest.java new file mode 100644 index 00000000..9527bdbc --- /dev/null +++ b/servant/src/test/java/com/iluwatar/servant/ServantTest.java @@ -0,0 +1,70 @@ +package com.iluwatar.servant; + +import org.junit.Test; + +import java.util.ArrayList; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +/** + * Date: 12/28/15 - 10:02 PM + * + * @author Jeroen Meulemeester + */ +public class ServantTest { + + @Test + public void testFeed() throws Exception { + final Royalty royalty = mock(Royalty.class); + final Servant servant = new Servant("test"); + servant.feed(royalty); + verify(royalty).getFed(); + verifyNoMoreInteractions(royalty); + } + + @Test + public void testGiveWine() throws Exception { + final Royalty royalty = mock(Royalty.class); + final Servant servant = new Servant("test"); + servant.giveWine(royalty); + verify(royalty).getDrink(); + verifyNoMoreInteractions(royalty); + } + + @Test + public void testGiveCompliments() throws Exception { + final Royalty royalty = mock(Royalty.class); + final Servant servant = new Servant("test"); + servant.giveCompliments(royalty); + verify(royalty).receiveCompliments(); + verifyNoMoreInteractions(royalty); + } + + @Test + public void testCheckIfYouWillBeHanged() throws Exception { + final Royalty goodMoodRoyalty = mock(Royalty.class); + when(goodMoodRoyalty.getMood()).thenReturn(true); + + final Royalty badMoodRoyalty = mock(Royalty.class); + when(badMoodRoyalty.getMood()).thenReturn(true); + + final ArrayList goodCompany = new ArrayList<>(); + goodCompany.add(goodMoodRoyalty); + goodCompany.add(goodMoodRoyalty); + goodCompany.add(goodMoodRoyalty); + + final ArrayList badCompany = new ArrayList<>(); + goodCompany.add(goodMoodRoyalty); + goodCompany.add(goodMoodRoyalty); + goodCompany.add(badMoodRoyalty); + + assertTrue(new Servant("test").checkIfYouWillBeHanged(goodCompany)); + assertTrue(new Servant("test").checkIfYouWillBeHanged(badCompany)); + + } + +} \ No newline at end of file From fcfdbe71f5ffe2daa7689e9318b44fe6aca9131c Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Tue, 29 Dec 2015 01:19:46 +0100 Subject: [PATCH 14/26] Added tests for service-layer pattern --- service-layer/pom.xml | 5 + .../servicelayer/common/BaseEntity.java | 31 +++- .../servicelayer/hibernate/HibernateUtil.java | 63 +++++--- .../servicelayer/spell/SpellDaoImpl.java | 5 +- .../servicelayer/spellbook/Spellbook.java | 3 +- .../iluwatar/servicelayer/app/AppTest.java | 9 ++ .../servicelayer/common/BaseDaoTest.java | 123 ++++++++++++++++ .../magic/MagicServiceImplTest.java | 138 ++++++++++++++++++ .../servicelayer/spell/SpellDaoImplTest.java | 35 +++++ .../spellbook/SpellbookDaoImplTest.java | 35 +++++ .../wizard/WizardDaoImplTest.java | 35 +++++ 11 files changed, 453 insertions(+), 29 deletions(-) create mode 100644 service-layer/src/test/java/com/iluwatar/servicelayer/common/BaseDaoTest.java create mode 100644 service-layer/src/test/java/com/iluwatar/servicelayer/magic/MagicServiceImplTest.java create mode 100644 service-layer/src/test/java/com/iluwatar/servicelayer/spell/SpellDaoImplTest.java create mode 100644 service-layer/src/test/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImplTest.java create mode 100644 service-layer/src/test/java/com/iluwatar/servicelayer/wizard/WizardDaoImplTest.java diff --git a/service-layer/pom.xml b/service-layer/pom.xml index b0a57cf5..7991b61d 100644 --- a/service-layer/pom.xml +++ b/service-layer/pom.xml @@ -22,5 +22,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/common/BaseEntity.java b/service-layer/src/main/java/com/iluwatar/servicelayer/common/BaseEntity.java index d8c79642..ab000092 100644 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/common/BaseEntity.java +++ b/service-layer/src/main/java/com/iluwatar/servicelayer/common/BaseEntity.java @@ -12,8 +12,37 @@ */ @MappedSuperclass @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) -public class BaseEntity { +public abstract class BaseEntity { @Version private Long version; + + /** + * Indicates the unique id of this entity + * + * @return The id of the entity, or 'null' when not persisted + */ + public abstract Long getId(); + + /** + * Set the id of this entity + * + * @param id The new id + */ + public abstract void setId(Long id); + + /** + * Get the name of this entity + * + * @return The name of the entity + */ + public abstract String getName(); + + /** + * Set the name of this entity + * + * @param name The new name + */ + public abstract void setName(final String name); + } diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/hibernate/HibernateUtil.java b/service-layer/src/main/java/com/iluwatar/servicelayer/hibernate/HibernateUtil.java index efc87dd1..9920a50d 100644 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/hibernate/HibernateUtil.java +++ b/service-layer/src/main/java/com/iluwatar/servicelayer/hibernate/HibernateUtil.java @@ -1,41 +1,56 @@ package com.iluwatar.servicelayer.hibernate; -import org.hibernate.SessionFactory; -import org.hibernate.cfg.Configuration; - import com.iluwatar.servicelayer.spell.Spell; import com.iluwatar.servicelayer.spellbook.Spellbook; import com.iluwatar.servicelayer.wizard.Wizard; +import org.hibernate.SessionFactory; +import org.hibernate.cfg.Configuration; + /** - * * Produces the Hibernate {@link SessionFactory}. - * */ public class HibernateUtil { - private static final SessionFactory SESSION_FACTORY; - - static { - try { - SESSION_FACTORY = - new Configuration().addAnnotatedClass(Wizard.class).addAnnotatedClass(Spellbook.class) - .addAnnotatedClass(Spell.class) - .setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect") - .setProperty("hibernate.connection.url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1") - .setProperty("hibernate.current_session_context_class", "thread") - .setProperty("hibernate.show_sql", "true") - .setProperty("hibernate.hbm2ddl.auto", "create-drop").buildSessionFactory(); - } catch (Throwable ex) { - System.err.println("Initial SessionFactory creation failed." + ex); - throw new ExceptionInInitializerError(ex); - } - } + /** + * The cached session factory + */ + private static volatile SessionFactory sessionFactory; private HibernateUtil() { } - public static SessionFactory getSessionFactory() { - return SESSION_FACTORY; + /** + * Create the current session factory instance, create a new one when there is none yet. + * + * @return The session factory + */ + public static synchronized SessionFactory getSessionFactory() { + if (sessionFactory == null) { + try { + sessionFactory = + new Configuration().addAnnotatedClass(Wizard.class).addAnnotatedClass(Spellbook.class) + .addAnnotatedClass(Spell.class) + .setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect") + .setProperty("hibernate.connection.url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1") + .setProperty("hibernate.current_session_context_class", "thread") + .setProperty("hibernate.show_sql", "true") + .setProperty("hibernate.hbm2ddl.auto", "create-drop").buildSessionFactory(); + } catch (Throwable ex) { + System.err.println("Initial SessionFactory creation failed." + ex); + throw new ExceptionInInitializerError(ex); + } + } + return sessionFactory; + } + + /** + * Drop the current connection, resulting in a create-drop clean database next time. This is + * mainly used for JUnit testing since one test should not influence the other + */ + public static void dropSession() { + getSessionFactory().close(); + sessionFactory = null; } + } diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDaoImpl.java b/service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDaoImpl.java index 66d06448..708ba033 100644 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDaoImpl.java +++ b/service-layer/src/main/java/com/iluwatar/servicelayer/spell/SpellDaoImpl.java @@ -1,12 +1,12 @@ package com.iluwatar.servicelayer.spell; +import com.iluwatar.servicelayer.common.DaoBaseImpl; + import org.hibernate.Criteria; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.criterion.Restrictions; -import com.iluwatar.servicelayer.common.DaoBaseImpl; - /** * * SpellDao implementation. @@ -24,7 +24,6 @@ public Spell findByName(String name) { Criteria criteria = session.createCriteria(persistentClass); criteria.add(Restrictions.eq("name", name)); result = (Spell) criteria.uniqueResult(); - result.getSpellbook().getWizards().size(); tx.commit(); } catch (Exception e) { if (tx != null) { diff --git a/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/Spellbook.java b/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/Spellbook.java index 49d81a95..165dcdc2 100644 --- a/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/Spellbook.java +++ b/service-layer/src/main/java/com/iluwatar/servicelayer/spellbook/Spellbook.java @@ -6,6 +6,7 @@ import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToMany; @@ -50,7 +51,7 @@ public void setId(Long id) { private String name; - @ManyToMany(mappedBy = "spellbooks") + @ManyToMany(mappedBy = "spellbooks", fetch = FetchType.EAGER) private Set wizards; @OneToMany(mappedBy = "spellbook", orphanRemoval = true, cascade = CascadeType.ALL) diff --git a/service-layer/src/test/java/com/iluwatar/servicelayer/app/AppTest.java b/service-layer/src/test/java/com/iluwatar/servicelayer/app/AppTest.java index 43e81d40..f92af7cf 100644 --- a/service-layer/src/test/java/com/iluwatar/servicelayer/app/AppTest.java +++ b/service-layer/src/test/java/com/iluwatar/servicelayer/app/AppTest.java @@ -1,5 +1,8 @@ package com.iluwatar.servicelayer.app; +import com.iluwatar.servicelayer.hibernate.HibernateUtil; + +import org.junit.After; import org.junit.Test; /** @@ -14,4 +17,10 @@ public void test() { String[] args = {}; App.main(args); } + + @After + public void tearDown() throws Exception { + HibernateUtil.dropSession(); + } + } diff --git a/service-layer/src/test/java/com/iluwatar/servicelayer/common/BaseDaoTest.java b/service-layer/src/test/java/com/iluwatar/servicelayer/common/BaseDaoTest.java new file mode 100644 index 00000000..1dabe117 --- /dev/null +++ b/service-layer/src/test/java/com/iluwatar/servicelayer/common/BaseDaoTest.java @@ -0,0 +1,123 @@ +package com.iluwatar.servicelayer.common; + +import com.iluwatar.servicelayer.hibernate.HibernateUtil; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +/** + * Date: 12/28/15 - 10:53 PM + * + * @author Jeroen Meulemeester + */ +public abstract class BaseDaoTest> { + + /** + * The number of entities stored before each test + */ + private static final int INITIAL_COUNT = 5; + + /** + * The unique id generator, shared between all entities + */ + private static final AtomicInteger ID_GENERATOR = new AtomicInteger(); + + /** + * Factory, used to create new entity instances with the given name + */ + private final Function factory; + + /** + * The tested data access object + */ + private final D dao; + + /** + * Create a new test using the given factory and dao + * + * @param factory The factory, used to create new entity instances with the given name + * @param dao The tested data access object + */ + public BaseDaoTest(final Function factory, final D dao) { + this.factory = factory; + this.dao = dao; + } + + @Before + public void setUp() throws Exception { + for (int i = 0; i < INITIAL_COUNT; i++) { + final String className = dao.persistentClass.getSimpleName(); + final String entityName = String.format("%s%d", className, ID_GENERATOR.incrementAndGet()); + this.dao.persist(this.factory.apply(entityName)); + } + } + + @After + public void tearDown() throws Exception { + HibernateUtil.dropSession(); + } + + protected final D getDao() { + return this.dao; + } + + @Test + public void testFind() throws Exception { + final List all = this.dao.findAll(); + for (final E entity : all) { + final E byId = this.dao.find(entity.getId()); + assertNotNull(byId); + assertEquals(byId.getId(), byId.getId()); + } + } + + @Test + public void testDelete() throws Exception { + final List originalEntities = this.dao.findAll(); + this.dao.delete(originalEntities.get(1)); + this.dao.delete(originalEntities.get(2)); + + final List entitiesLeft = this.dao.findAll(); + assertNotNull(entitiesLeft); + assertEquals(INITIAL_COUNT - 2, entitiesLeft.size()); + } + + @Test + public void testFindAll() throws Exception { + final List all = this.dao.findAll(); + assertNotNull(all); + assertEquals(INITIAL_COUNT, all.size()); + } + + @Test + public void testSetId() throws Exception { + final E entity = this.factory.apply("name"); + assertNull(entity.getId()); + + final Long expectedId = Long.valueOf(1); + entity.setId(expectedId); + assertEquals(expectedId, entity.getId()); + } + + @Test + public void testSetName() throws Exception { + final E entity = this.factory.apply("name"); + assertEquals("name", entity.getName()); + assertEquals("name", entity.toString()); + + final String expectedName = "new name"; + entity.setName(expectedName); + assertEquals(expectedName, entity.getName()); + assertEquals(expectedName, entity.toString()); + } + +} \ No newline at end of file diff --git a/service-layer/src/test/java/com/iluwatar/servicelayer/magic/MagicServiceImplTest.java b/service-layer/src/test/java/com/iluwatar/servicelayer/magic/MagicServiceImplTest.java new file mode 100644 index 00000000..48f3ae9d --- /dev/null +++ b/service-layer/src/test/java/com/iluwatar/servicelayer/magic/MagicServiceImplTest.java @@ -0,0 +1,138 @@ +package com.iluwatar.servicelayer.magic; + +import com.iluwatar.servicelayer.spell.Spell; +import com.iluwatar.servicelayer.spell.SpellDao; +import com.iluwatar.servicelayer.spellbook.Spellbook; +import com.iluwatar.servicelayer.spellbook.SpellbookDao; +import com.iluwatar.servicelayer.wizard.Wizard; +import com.iluwatar.servicelayer.wizard.WizardDao; + +import org.junit.Test; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +/** + * Date: 12/29/15 - 12:06 AM + * + * @author Jeroen Meulemeester + */ +public class MagicServiceImplTest { + + @Test + public void testFindAllWizards() throws Exception { + final WizardDao wizardDao = mock(WizardDao.class); + final SpellbookDao spellbookDao = mock(SpellbookDao.class); + final SpellDao spellDao = mock(SpellDao.class); + + final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao); + verifyZeroInteractions(wizardDao, spellbookDao, spellDao); + + service.findAllWizards(); + verify(wizardDao).findAll(); + verifyNoMoreInteractions(wizardDao, spellbookDao, spellDao); + } + + @Test + public void testFindAllSpellbooks() throws Exception { + final WizardDao wizardDao = mock(WizardDao.class); + final SpellbookDao spellbookDao = mock(SpellbookDao.class); + final SpellDao spellDao = mock(SpellDao.class); + + final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao); + verifyZeroInteractions(wizardDao, spellbookDao, spellDao); + + service.findAllSpellbooks(); + verify(spellbookDao).findAll(); + verifyNoMoreInteractions(wizardDao, spellbookDao, spellDao); + } + + @Test + public void testFindAllSpells() throws Exception { + final WizardDao wizardDao = mock(WizardDao.class); + final SpellbookDao spellbookDao = mock(SpellbookDao.class); + final SpellDao spellDao = mock(SpellDao.class); + + final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao); + verifyZeroInteractions(wizardDao, spellbookDao, spellDao); + + service.findAllSpells(); + verify(spellDao).findAll(); + verifyNoMoreInteractions(wizardDao, spellbookDao, spellDao); + } + + @Test + public void testFindWizardsWithSpellbook() throws Exception { + final String bookname = "bookname"; + final Spellbook spellbook = mock(Spellbook.class); + final Set wizards = new HashSet<>(); + wizards.add(mock(Wizard.class)); + wizards.add(mock(Wizard.class)); + wizards.add(mock(Wizard.class)); + + when(spellbook.getWizards()).thenReturn(wizards); + + final SpellbookDao spellbookDao = mock(SpellbookDao.class); + when(spellbookDao.findByName(eq(bookname))).thenReturn(spellbook); + + final WizardDao wizardDao = mock(WizardDao.class); + final SpellDao spellDao = mock(SpellDao.class); + + + final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao); + verifyZeroInteractions(wizardDao, spellbookDao, spellDao, spellbook); + + final List result = service.findWizardsWithSpellbook(bookname); + verify(spellbookDao).findByName(eq(bookname)); + verify(spellbook).getWizards(); + + assertNotNull(result); + assertEquals(3, result.size()); + + verifyNoMoreInteractions(wizardDao, spellbookDao, spellDao); + } + + @Test + public void testFindWizardsWithSpell() throws Exception { + final Set wizards = new HashSet<>(); + wizards.add(mock(Wizard.class)); + wizards.add(mock(Wizard.class)); + wizards.add(mock(Wizard.class)); + + final Spellbook spellbook = mock(Spellbook.class); + when(spellbook.getWizards()).thenReturn(wizards); + + final SpellbookDao spellbookDao = mock(SpellbookDao.class); + final WizardDao wizardDao = mock(WizardDao.class); + + final Spell spell = mock(Spell.class); + when(spell.getSpellbook()).thenReturn(spellbook); + + final String spellName = "spellname"; + final SpellDao spellDao = mock(SpellDao.class); + when(spellDao.findByName(eq(spellName))).thenReturn(spell); + + final MagicServiceImpl service = new MagicServiceImpl(wizardDao, spellbookDao, spellDao); + verifyZeroInteractions(wizardDao, spellbookDao, spellDao, spellbook); + + final List result = service.findWizardsWithSpell(spellName); + verify(spellDao).findByName(eq(spellName)); + verify(spellbook).getWizards(); + + assertNotNull(result); + assertEquals(3, result.size()); + + verifyNoMoreInteractions(wizardDao, spellbookDao, spellDao); + } + +} diff --git a/service-layer/src/test/java/com/iluwatar/servicelayer/spell/SpellDaoImplTest.java b/service-layer/src/test/java/com/iluwatar/servicelayer/spell/SpellDaoImplTest.java new file mode 100644 index 00000000..99a8e142 --- /dev/null +++ b/service-layer/src/test/java/com/iluwatar/servicelayer/spell/SpellDaoImplTest.java @@ -0,0 +1,35 @@ +package com.iluwatar.servicelayer.spell; + +import com.iluwatar.servicelayer.common.BaseDaoTest; + +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Date: 12/28/15 - 11:02 PM + * + * @author Jeroen Meulemeester + */ +public class SpellDaoImplTest extends BaseDaoTest { + + public SpellDaoImplTest() { + super(Spell::new, new SpellDaoImpl()); + } + + @Test + public void testFindByName() throws Exception { + final SpellDaoImpl dao = getDao(); + final List allSpells = dao.findAll(); + for (final Spell spell : allSpells) { + final Spell spellByName = dao.findByName(spell.getName()); + assertNotNull(spellByName); + assertEquals(spell.getId(), spellByName.getId()); + assertEquals(spell.getName(), spellByName.getName()); + } + } + +} diff --git a/service-layer/src/test/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImplTest.java b/service-layer/src/test/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImplTest.java new file mode 100644 index 00000000..fda46009 --- /dev/null +++ b/service-layer/src/test/java/com/iluwatar/servicelayer/spellbook/SpellbookDaoImplTest.java @@ -0,0 +1,35 @@ +package com.iluwatar.servicelayer.spellbook; + +import com.iluwatar.servicelayer.common.BaseDaoTest; + +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Date: 12/28/15 - 11:44 PM + * + * @author Jeroen Meulemeester + */ +public class SpellbookDaoImplTest extends BaseDaoTest { + + public SpellbookDaoImplTest() { + super(Spellbook::new, new SpellbookDaoImpl()); + } + + @Test + public void testFindByName() throws Exception { + final SpellbookDaoImpl dao = getDao(); + final List allBooks = dao.findAll(); + for (final Spellbook book : allBooks) { + final Spellbook spellByName = dao.findByName(book.getName()); + assertNotNull(spellByName); + assertEquals(book.getId(), spellByName.getId()); + assertEquals(book.getName(), spellByName.getName()); + } + } + +} diff --git a/service-layer/src/test/java/com/iluwatar/servicelayer/wizard/WizardDaoImplTest.java b/service-layer/src/test/java/com/iluwatar/servicelayer/wizard/WizardDaoImplTest.java new file mode 100644 index 00000000..1812f4c3 --- /dev/null +++ b/service-layer/src/test/java/com/iluwatar/servicelayer/wizard/WizardDaoImplTest.java @@ -0,0 +1,35 @@ +package com.iluwatar.servicelayer.wizard; + +import com.iluwatar.servicelayer.common.BaseDaoTest; + +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Date: 12/28/15 - 11:46 PM + * + * @author Jeroen Meulemeester + */ +public class WizardDaoImplTest extends BaseDaoTest { + + public WizardDaoImplTest() { + super(Wizard::new, new WizardDaoImpl()); + } + + @Test + public void testFindByName() throws Exception { + final WizardDaoImpl dao = getDao(); + final List allWizards = dao.findAll(); + for (final Wizard spell : allWizards) { + final Wizard byName = dao.findByName(spell.getName()); + assertNotNull(byName); + assertEquals(spell.getId(), byName.getId()); + assertEquals(spell.getName(), byName.getName()); + } + } + +} From a375b2d28b4ba18e37756bec36e1d667d16afba2 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Tue, 29 Dec 2015 19:25:29 +0100 Subject: [PATCH 15/26] Added tests for service-locator pattern Fix NPE when requested service is unknown --- .../servicelocator/ServiceLocator.java | 4 +- .../servicelocator/ServiceLocatorTest.java | 42 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 service-locator/src/test/java/com/iluwatar/servicelocator/ServiceLocatorTest.java diff --git a/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceLocator.java b/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceLocator.java index 6fb361ca..6ec51b98 100644 --- a/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceLocator.java +++ b/service-locator/src/main/java/com/iluwatar/servicelocator/ServiceLocator.java @@ -32,7 +32,9 @@ public static Service getService(String serviceJndiName) { */ InitContext ctx = new InitContext(); serviceObj = (Service) ctx.lookup(serviceJndiName); - serviceCache.addService(serviceObj); + if (serviceObj != null) { // Only cache a service if it actually exists + serviceCache.addService(serviceObj); + } return serviceObj; } } diff --git a/service-locator/src/test/java/com/iluwatar/servicelocator/ServiceLocatorTest.java b/service-locator/src/test/java/com/iluwatar/servicelocator/ServiceLocatorTest.java new file mode 100644 index 00000000..e50dbe02 --- /dev/null +++ b/service-locator/src/test/java/com/iluwatar/servicelocator/ServiceLocatorTest.java @@ -0,0 +1,42 @@ +package com.iluwatar.servicelocator; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Date: 12/29/15 - 19:07 PM + * + * @author Jeroen Meulemeester + */ +public class ServiceLocatorTest { + + /** + * Verify if we just receive 'null' when requesting a non-existing service + */ + @Test + public void testGetNonExistentService() { + assertNull(ServiceLocator.getService("fantastic/unicorn/service")); + assertNull(ServiceLocator.getService("another/fantastic/unicorn/service")); + } + + /** + * Verify if we get the same cached instance when requesting the same service twice + */ + @Test + public void testServiceCache() { + final String[] serviceNames = new String[]{ + "jndi/serviceA", "jndi/serviceB" + }; + + for (final String serviceName : serviceNames) { + final Service service = ServiceLocator.getService(serviceName); + assertNotNull(service); + assertEquals(serviceName, service.getName()); + assertTrue(service.getId() > 0); // The id is generated randomly, but the minimum value is '1' + assertSame(service, ServiceLocator.getService(serviceName)); + } + + } + +} \ No newline at end of file From d0cdf84936ac0e7908f8d76faa63e8f4c1e69c29 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Tue, 29 Dec 2015 19:28:04 +0100 Subject: [PATCH 16/26] Added tests for singleton pattern --- .../singleton/EnumIvoryTowerTest.java | 17 ++++ .../InitializingOnDemandHolderIdiomTest.java | 17 ++++ .../iluwatar/singleton/IvoryTowerTest.java | 17 ++++ .../LazyLoadedSingletonThreadSafetyTest.java | 90 ------------------- .../com/iluwatar/singleton/SingletonTest.java | 88 ++++++++++++++++++ .../ThreadSafeDoubleCheckLockingTest.java | 17 ++++ .../ThreadSafeLazyLoadedIvoryTowerTest.java | 17 ++++ 7 files changed, 173 insertions(+), 90 deletions(-) create mode 100644 singleton/src/test/java/com/iluwatar/singleton/EnumIvoryTowerTest.java create mode 100644 singleton/src/test/java/com/iluwatar/singleton/InitializingOnDemandHolderIdiomTest.java create mode 100644 singleton/src/test/java/com/iluwatar/singleton/IvoryTowerTest.java delete mode 100644 singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java create mode 100644 singleton/src/test/java/com/iluwatar/singleton/SingletonTest.java create mode 100644 singleton/src/test/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLockingTest.java create mode 100644 singleton/src/test/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTowerTest.java diff --git a/singleton/src/test/java/com/iluwatar/singleton/EnumIvoryTowerTest.java b/singleton/src/test/java/com/iluwatar/singleton/EnumIvoryTowerTest.java new file mode 100644 index 00000000..49c65c71 --- /dev/null +++ b/singleton/src/test/java/com/iluwatar/singleton/EnumIvoryTowerTest.java @@ -0,0 +1,17 @@ +package com.iluwatar.singleton; + +/** + * Date: 12/29/15 - 19:20 PM + * + * @author Jeroen Meulemeester + */ +public class EnumIvoryTowerTest extends SingletonTest { + + /** + * Create a new singleton test instance using the given 'getInstance' method + */ + public EnumIvoryTowerTest() { + super(() -> EnumIvoryTower.INSTANCE); + } + +} diff --git a/singleton/src/test/java/com/iluwatar/singleton/InitializingOnDemandHolderIdiomTest.java b/singleton/src/test/java/com/iluwatar/singleton/InitializingOnDemandHolderIdiomTest.java new file mode 100644 index 00000000..60ae4798 --- /dev/null +++ b/singleton/src/test/java/com/iluwatar/singleton/InitializingOnDemandHolderIdiomTest.java @@ -0,0 +1,17 @@ +package com.iluwatar.singleton; + +/** + * Date: 12/29/15 - 19:22 PM + * + * @author Jeroen Meulemeester + */ +public class InitializingOnDemandHolderIdiomTest extends SingletonTest { + + /** + * Create a new singleton test instance using the given 'getInstance' method + */ + public InitializingOnDemandHolderIdiomTest() { + super(InitializingOnDemandHolderIdiom::getInstance); + } + +} \ No newline at end of file diff --git a/singleton/src/test/java/com/iluwatar/singleton/IvoryTowerTest.java b/singleton/src/test/java/com/iluwatar/singleton/IvoryTowerTest.java new file mode 100644 index 00000000..e9a222ae --- /dev/null +++ b/singleton/src/test/java/com/iluwatar/singleton/IvoryTowerTest.java @@ -0,0 +1,17 @@ +package com.iluwatar.singleton; + +/** + * Date: 12/29/15 - 19:23 PM + * + * @author Jeroen Meulemeester + */ +public class IvoryTowerTest extends SingletonTest { + + /** + * Create a new singleton test instance using the given 'getInstance' method + */ + public IvoryTowerTest() { + super(IvoryTower::getInstance); + } + +} \ No newline at end of file diff --git a/singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java b/singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java deleted file mode 100644 index 24cd7cf4..00000000 --- a/singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.iluwatar.singleton; - -import static org.junit.Assert.assertEquals; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; - -import org.junit.Test; - -/** - * This class provides several test case that test singleton construction. - * - * The first proves that multiple calls to the singleton getInstance object are the same when called - * in the SAME thread. The second proves that multiple calls to the singleton getInstance object are - * the same when called in the DIFFERENT thread. - * - */ -public class LazyLoadedSingletonThreadSafetyTest { - - private static final int NUM_THREADS = 5; - private List threadObjects = Collections - .synchronizedList(new ArrayList<>()); - - // NullObject class so Callable has to return something - private class NullObject { - private NullObject() {} - } - - @Test - public void testMultipleCallsReturnTheSameObjectInSameThread() { - // Create several instances in the same calling thread - ThreadSafeLazyLoadedIvoryTower instance1 = ThreadSafeLazyLoadedIvoryTower.getInstance(); - ThreadSafeLazyLoadedIvoryTower instance2 = ThreadSafeLazyLoadedIvoryTower.getInstance(); - ThreadSafeLazyLoadedIvoryTower instance3 = ThreadSafeLazyLoadedIvoryTower.getInstance(); - // now check they are equal - assertEquals(instance1, instance1); - assertEquals(instance1, instance2); - assertEquals(instance2, instance3); - assertEquals(instance1, instance3); - } - - @Test - public void testMultipleCallsReturnTheSameObjectInDifferentThreads() - throws InterruptedException, ExecutionException { - { - // create several threads and inside each callable instantiate the singleton class - ExecutorService executorService = Executors.newSingleThreadExecutor(); - - List> threadList = new ArrayList<>(); - for (int i = 0; i < NUM_THREADS; i++) { - threadList.add(new SingletonCreatingThread()); - } - - ExecutorService service = Executors.newCachedThreadPool(); - List> results = service.invokeAll(threadList); - - // wait for all of the threads to complete - for (Future res : results) { - res.get(); - } - - // tidy up the executor - executorService.shutdown(); - } - { - // now check the contents that were added to threadObjects by each thread - assertEquals(NUM_THREADS, threadObjects.size()); - assertEquals(threadObjects.get(0), threadObjects.get(1)); - assertEquals(threadObjects.get(1), threadObjects.get(2)); - assertEquals(threadObjects.get(2), threadObjects.get(3)); - assertEquals(threadObjects.get(3), threadObjects.get(4)); - } - } - - private class SingletonCreatingThread implements Callable { - @Override - public NullObject call() { - // instantiate the thread safety class and add to list to test afterwards - ThreadSafeLazyLoadedIvoryTower instance = ThreadSafeLazyLoadedIvoryTower.getInstance(); - threadObjects.add(instance); - return new NullObject();// return null object (cannot return Void) - } - } -} diff --git a/singleton/src/test/java/com/iluwatar/singleton/SingletonTest.java b/singleton/src/test/java/com/iluwatar/singleton/SingletonTest.java new file mode 100644 index 00000000..6c6c4a3f --- /dev/null +++ b/singleton/src/test/java/com/iluwatar/singleton/SingletonTest.java @@ -0,0 +1,88 @@ +package com.iluwatar.singleton; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.function.Supplier; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; + +/** + * This class provides several test case that test singleton construction. + * + * The first proves that multiple calls to the singleton getInstance object are the same when called + * in the SAME thread. The second proves that multiple calls to the singleton getInstance object are + * the same when called in the DIFFERENT thread. + * + * Date: 12/29/15 - 19:25 PM + * + * @author Jeroen Meulemeester + * @author Richard Jones + */ +public abstract class SingletonTest { + + /** + * The singleton's getInstance method + */ + private final Supplier singletonInstanceMethod; + + /** + * Create a new singleton test instance using the given 'getInstance' method + * + * @param singletonInstanceMethod The singleton's getInstance method + */ + public SingletonTest(final Supplier singletonInstanceMethod) { + this.singletonInstanceMethod = singletonInstanceMethod; + } + + /** + * Test the singleton in a non-concurrent setting + */ + @Test + public void testMultipleCallsReturnTheSameObjectInSameThread() { + // Create several instances in the same calling thread + S instance1 = this.singletonInstanceMethod.get(); + S instance2 = this.singletonInstanceMethod.get(); + S instance3 = this.singletonInstanceMethod.get(); + // now check they are equal + assertSame(instance1, instance2); + assertSame(instance1, instance3); + assertSame(instance2, instance3); + } + + /** + * Test singleton instance in a concurrent setting + */ + @Test(timeout = 10000) + public void testMultipleCallsReturnTheSameObjectInDifferentThreads() throws Exception { + + // Create 10000 tasks and inside each callable instantiate the singleton class + final List> tasks = new ArrayList<>(); + for (int i = 0; i < 10000; i++) { + tasks.add(this.singletonInstanceMethod::get); + } + + // Use up to 8 concurrent threads to handle the tasks + final ExecutorService executorService = Executors.newFixedThreadPool(8); + final List> results = executorService.invokeAll(tasks); + + // wait for all of the threads to complete + final S expectedInstance = this.singletonInstanceMethod.get(); + for (Future res : results) { + final S instance = res.get(); + assertNotNull(instance); + assertSame(expectedInstance, instance); + } + + // tidy up the executor + executorService.shutdown(); + + } + +} diff --git a/singleton/src/test/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLockingTest.java b/singleton/src/test/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLockingTest.java new file mode 100644 index 00000000..f40f0cbc --- /dev/null +++ b/singleton/src/test/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLockingTest.java @@ -0,0 +1,17 @@ +package com.iluwatar.singleton; + +/** + * Date: 12/29/15 - 19:26 PM + * + * @author Jeroen Meulemeester + */ +public class ThreadSafeDoubleCheckLockingTest extends SingletonTest { + + /** + * Create a new singleton test instance using the given 'getInstance' method + */ + public ThreadSafeDoubleCheckLockingTest() { + super(ThreadSafeDoubleCheckLocking::getInstance); + } + +} \ No newline at end of file diff --git a/singleton/src/test/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTowerTest.java b/singleton/src/test/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTowerTest.java new file mode 100644 index 00000000..8f2a5e6e --- /dev/null +++ b/singleton/src/test/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTowerTest.java @@ -0,0 +1,17 @@ +package com.iluwatar.singleton; + +/** + * Date: 12/29/15 - 19:26 PM + * + * @author Jeroen Meulemeester + */ +public class ThreadSafeLazyLoadedIvoryTowerTest extends SingletonTest { + + /** + * Create a new singleton test instance using the given 'getInstance' method + */ + public ThreadSafeLazyLoadedIvoryTowerTest() { + super(ThreadSafeLazyLoadedIvoryTower::getInstance); + } + +} From 5611f26c77cf48b60008408a4cd033e5ffb85c35 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Tue, 29 Dec 2015 20:12:53 +0100 Subject: [PATCH 17/26] Added tests for specification pattern --- specification/pom.xml | 5 + .../specification/creature/CreatureTest.java | 111 ++++++++++++++++++ .../selector/ColorSelectorTest.java | 37 ++++++ .../selector/MovementSelectorTest.java | 38 ++++++ .../selector/SizeSelectorTest.java | 36 ++++++ 5 files changed, 227 insertions(+) create mode 100644 specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java create mode 100644 specification/src/test/java/com/iluwatar/specification/selector/ColorSelectorTest.java create mode 100644 specification/src/test/java/com/iluwatar/specification/selector/MovementSelectorTest.java create mode 100644 specification/src/test/java/com/iluwatar/specification/selector/SizeSelectorTest.java diff --git a/specification/pom.xml b/specification/pom.xml index 8c79fa9e..5bf50dbc 100644 --- a/specification/pom.xml +++ b/specification/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java b/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java new file mode 100644 index 00000000..0548788a --- /dev/null +++ b/specification/src/test/java/com/iluwatar/specification/creature/CreatureTest.java @@ -0,0 +1,111 @@ +package com.iluwatar.specification.creature; + +import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Movement; +import com.iluwatar.specification.property.Size; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.Arrays; +import java.util.Collection; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Date: 12/29/15 - 7:47 PM + * + * @author Jeroen Meulemeester + */ +@RunWith(Parameterized.class) +public class CreatureTest { + + /** + * @return The tested {@link Creature} instance and its expected specs + */ + @Parameterized.Parameters + public static Collection data() { + return Arrays.asList( + new Object[]{new Dragon(), "Dragon", Size.LARGE, Movement.FLYING, Color.RED}, + new Object[]{new Goblin(), "Goblin", Size.SMALL, Movement.WALKING, Color.GREEN}, + new Object[]{new KillerBee(), "KillerBee", Size.SMALL, Movement.FLYING, Color.LIGHT}, + new Object[]{new Octopus(), "Octopus", Size.NORMAL, Movement.SWIMMING, Color.DARK}, + new Object[]{new Shark(), "Shark", Size.NORMAL, Movement.SWIMMING, Color.LIGHT}, + new Object[]{new Troll(), "Troll", Size.LARGE, Movement.WALKING, Color.DARK} + ); + } + + /** + * The tested creature + */ + private final Creature testedCreature; + + /** + * The expected name of the tested creature + */ + private final String name; + + /** + * The expected size of the tested creature + */ + private final Size size; + + /** + * The expected movement type of the tested creature + */ + private final Movement movement; + + /** + * The expected color of the tested creature + */ + private final Color color; + + /** + * @param testedCreature The tested creature + * @param name The expected name of the creature + * @param size The expected size of the creature + * @param movement The expected movement type of the creature + * @param color The expected color of the creature + */ + public CreatureTest(final Creature testedCreature, final String name, final Size size, + final Movement movement, final Color color) { + this.testedCreature = testedCreature; + this.name = name; + this.size = size; + this.movement = movement; + this.color = color; + } + + + @Test + public void testGetName() throws Exception { + assertEquals(this.name, this.testedCreature.getName()); + } + + @Test + public void testGetSize() throws Exception { + assertEquals(this.size, this.testedCreature.getSize()); + } + + @Test + public void testGetMovement() throws Exception { + assertEquals(this.movement, this.testedCreature.getMovement()); + } + + @Test + public void testGetColor() throws Exception { + assertEquals(this.color, this.testedCreature.getColor()); + } + + @Test + public void testToString() throws Exception { + final String toString = this.testedCreature.toString(); + assertNotNull(toString); + assertEquals( + String.format("%s [size=%s, movement=%s, color=%s]", name, size, movement, color), + toString + ); + } +} \ No newline at end of file diff --git a/specification/src/test/java/com/iluwatar/specification/selector/ColorSelectorTest.java b/specification/src/test/java/com/iluwatar/specification/selector/ColorSelectorTest.java new file mode 100644 index 00000000..894f6c58 --- /dev/null +++ b/specification/src/test/java/com/iluwatar/specification/selector/ColorSelectorTest.java @@ -0,0 +1,37 @@ +package com.iluwatar.specification.selector; + +import com.iluwatar.specification.creature.Creature; +import com.iluwatar.specification.property.Color; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Date: 12/29/15 - 7:35 PM + * + * @author Jeroen Meulemeester + */ +public class ColorSelectorTest { + + /** + * Verify if the color selector gives the correct results + */ + @Test + public void testColor() { + final Creature greenCreature = mock(Creature.class); + when(greenCreature.getColor()).thenReturn(Color.GREEN); + + final Creature redCreature = mock(Creature.class); + when(redCreature.getColor()).thenReturn(Color.RED); + + final ColorSelector greenSelector = new ColorSelector(Color.GREEN); + assertTrue(greenSelector.test(greenCreature)); + assertFalse(greenSelector.test(redCreature)); + + } + +} \ No newline at end of file diff --git a/specification/src/test/java/com/iluwatar/specification/selector/MovementSelectorTest.java b/specification/src/test/java/com/iluwatar/specification/selector/MovementSelectorTest.java new file mode 100644 index 00000000..c2a251b5 --- /dev/null +++ b/specification/src/test/java/com/iluwatar/specification/selector/MovementSelectorTest.java @@ -0,0 +1,38 @@ +package com.iluwatar.specification.selector; + +import com.iluwatar.specification.creature.Creature; +import com.iluwatar.specification.property.Color; +import com.iluwatar.specification.property.Movement; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Date: 12/29/15 - 7:37 PM + * + * @author Jeroen Meulemeester + */ +public class MovementSelectorTest { + + /** + * Verify if the movement selector gives the correct results + */ + @Test + public void testMovement() { + final Creature swimmingCreature = mock(Creature.class); + when(swimmingCreature.getMovement()).thenReturn(Movement.SWIMMING); + + final Creature flyingCreature = mock(Creature.class); + when(flyingCreature.getMovement()).thenReturn(Movement.FLYING); + + final MovementSelector swimmingSelector = new MovementSelector(Movement.SWIMMING); + assertTrue(swimmingSelector.test(swimmingCreature)); + assertFalse(swimmingSelector.test(flyingCreature)); + + } + +} \ No newline at end of file diff --git a/specification/src/test/java/com/iluwatar/specification/selector/SizeSelectorTest.java b/specification/src/test/java/com/iluwatar/specification/selector/SizeSelectorTest.java new file mode 100644 index 00000000..d2a534c1 --- /dev/null +++ b/specification/src/test/java/com/iluwatar/specification/selector/SizeSelectorTest.java @@ -0,0 +1,36 @@ +package com.iluwatar.specification.selector; + +import com.iluwatar.specification.creature.Creature; +import com.iluwatar.specification.property.Size; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Date: 12/29/15 - 7:43 PM + * + * @author Jeroen Meulemeester + */ +public class SizeSelectorTest { + + /** + * Verify if the size selector gives the correct results + */ + @Test + public void testMovement() { + final Creature normalCreature = mock(Creature.class); + when(normalCreature.getSize()).thenReturn(Size.NORMAL); + + final Creature smallCreature = mock(Creature.class); + when(smallCreature.getSize()).thenReturn(Size.SMALL); + + final SizeSelector normalSelector = new SizeSelector(Size.NORMAL); + assertTrue(normalSelector.test(normalCreature)); + assertFalse(normalSelector.test(smallCreature)); + } + +} From 1d9aff407191c7b996734edc164cb8bb1eadcf0d Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Tue, 29 Dec 2015 20:39:26 +0100 Subject: [PATCH 18/26] Added tests for state pattern --- state/pom.xml | 5 ++ .../test/java/com/iluwatar/state/AppTest.java | 2 + .../java/com/iluwatar/state/MammothTest.java | 90 +++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 state/src/test/java/com/iluwatar/state/MammothTest.java diff --git a/state/pom.xml b/state/pom.xml index 8aa1ae81..cfa94a0e 100644 --- a/state/pom.xml +++ b/state/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/state/src/test/java/com/iluwatar/state/AppTest.java b/state/src/test/java/com/iluwatar/state/AppTest.java index a629ac44..37422e4e 100644 --- a/state/src/test/java/com/iluwatar/state/AppTest.java +++ b/state/src/test/java/com/iluwatar/state/AppTest.java @@ -1,5 +1,6 @@ package com.iluwatar.state; +import org.junit.Ignore; import org.junit.Test; /** @@ -10,6 +11,7 @@ public class AppTest { @Test + @Ignore public void test() { String[] args = {}; App.main(args); diff --git a/state/src/test/java/com/iluwatar/state/MammothTest.java b/state/src/test/java/com/iluwatar/state/MammothTest.java new file mode 100644 index 00000000..4f722420 --- /dev/null +++ b/state/src/test/java/com/iluwatar/state/MammothTest.java @@ -0,0 +1,90 @@ +package com.iluwatar.state; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InOrder; +import org.mockito.Mockito; + +import java.io.PrintStream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; + +/** + * Date: 12/29/15 - 8:27 PM + * + * @author Jeroen Meulemeester + */ +public class MammothTest { + + /** + * The mocked standard out {@link PrintStream}, required since some actions don't have any + * influence on accessible objects, except for writing to std-out using {@link System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Switch to a complete mammoth 'mood'-cycle and verify if the observed mood matches the expected + * value. + */ + @Test + public void testTimePasses() { + final InOrder inOrder = Mockito.inOrder(this.stdOutMock); + final Mammoth mammoth = new Mammoth(); + + mammoth.observe(); + inOrder.verify(this.stdOutMock).println("The mammoth is calm and peaceful."); + inOrder.verifyNoMoreInteractions(); + + mammoth.timePasses(); + inOrder.verify(this.stdOutMock).println("The mammoth gets angry!"); + inOrder.verifyNoMoreInteractions(); + + mammoth.observe(); + inOrder.verify(this.stdOutMock).println("The mammoth is furious!"); + inOrder.verifyNoMoreInteractions(); + + mammoth.timePasses(); + inOrder.verify(this.stdOutMock).println("The mammoth calms down."); + inOrder.verifyNoMoreInteractions(); + + mammoth.observe(); + inOrder.verify(this.stdOutMock).println("The mammoth is calm and peaceful."); + inOrder.verifyNoMoreInteractions(); + + } + + /** + * Verify if {@link Mammoth#toString()} gives the expected value + */ + @Test + public void testToString() { + final String toString = new Mammoth().toString(); + assertNotNull(toString); + assertEquals("The mammoth", toString); + } + +} \ No newline at end of file From 2e2707862abfd9c49786b8883e70eca5c07eabd3 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Tue, 29 Dec 2015 21:05:53 +0100 Subject: [PATCH 19/26] Fixed checkstyle code quality issues --- .../java/com/iluwatar/nullobject/TreeTest.java | 14 +++++++------- .../com/iluwatar/poison/pill/ConsumerTest.java | 8 ++++---- .../com/iluwatar/privateclassdata/StewTest.java | 4 ++-- .../iluwatar/producer/consumer/ConsumerTest.java | 2 +- .../com/iluwatar/proxy/WizardTowerProxyTest.java | 8 ++++---- .../java/com/iluwatar/proxy/WizardTowerTest.java | 8 ++++---- .../servicelocator/ServiceLocatorTest.java | 8 ++++++-- .../src/test/java/com/iluwatar/state/AppTest.java | 4 +--- 8 files changed, 29 insertions(+), 27 deletions(-) diff --git a/null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java b/null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java index 3599dd4c..5d796858 100644 --- a/null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java +++ b/null-object/src/test/java/com/iluwatar/nullobject/TreeTest.java @@ -32,13 +32,13 @@ public class TreeTest extends StdOutTest { private static final Node TREE_ROOT; static { - final NodeImpl level1_b = new NodeImpl("level1_b", NullNode.getInstance(), NullNode.getInstance()); - final NodeImpl level2_b = new NodeImpl("level2_b", NullNode.getInstance(), NullNode.getInstance()); - final NodeImpl level3_a = new NodeImpl("level3_a", NullNode.getInstance(), NullNode.getInstance()); - final NodeImpl level3_b = new NodeImpl("level3_b", NullNode.getInstance(), NullNode.getInstance()); - final NodeImpl level2_a = new NodeImpl("level2_a", level3_a, level3_b); - final NodeImpl level1_a = new NodeImpl("level1_a", level2_a, level2_b); - TREE_ROOT = new NodeImpl("root", level1_a, level1_b); + final NodeImpl level1B = new NodeImpl("level1_b", NullNode.getInstance(), NullNode.getInstance()); + final NodeImpl level2B = new NodeImpl("level2_b", NullNode.getInstance(), NullNode.getInstance()); + final NodeImpl level3A = new NodeImpl("level3_a", NullNode.getInstance(), NullNode.getInstance()); + final NodeImpl level3B = new NodeImpl("level3_b", NullNode.getInstance(), NullNode.getInstance()); + final NodeImpl level2A = new NodeImpl("level2_a", level3A, level3B); + final NodeImpl level1A = new NodeImpl("level1_a", level2A, level2B); + TREE_ROOT = new NodeImpl("root", level1A, level1B); } /** diff --git a/poison-pill/src/test/java/com/iluwatar/poison/pill/ConsumerTest.java b/poison-pill/src/test/java/com/iluwatar/poison/pill/ConsumerTest.java index 1c92f10d..c152fbbd 100644 --- a/poison-pill/src/test/java/com/iluwatar/poison/pill/ConsumerTest.java +++ b/poison-pill/src/test/java/com/iluwatar/poison/pill/ConsumerTest.java @@ -17,10 +17,10 @@ public class ConsumerTest extends StdOutTest { @Test public void testConsume() throws Exception { final Message[] messages = new Message[]{ - createMessage("you", "Hello!"), - createMessage("me", "Hi!"), - Message.POISON_PILL, - createMessage("late_for_the_party", "Hello? Anyone here?"), + createMessage("you", "Hello!"), + createMessage("me", "Hi!"), + Message.POISON_PILL, + createMessage("late_for_the_party", "Hello? Anyone here?"), }; final MessageQueue queue = new SimpleMessageQueue(messages.length); diff --git a/private-class-data/src/test/java/com/iluwatar/privateclassdata/StewTest.java b/private-class-data/src/test/java/com/iluwatar/privateclassdata/StewTest.java index d6b67a35..8e0452fa 100644 --- a/private-class-data/src/test/java/com/iluwatar/privateclassdata/StewTest.java +++ b/private-class-data/src/test/java/com/iluwatar/privateclassdata/StewTest.java @@ -18,8 +18,8 @@ public class StewTest extends StdOutTest { @Test public void testMix() { final ImmutableStew stew = new ImmutableStew(1, 2, 3, 4); - final String expectedMessage = "Mixing the immutable stew we find: 1 potatoes, " + - "2 carrots, 3 meat and 4 peppers"; + final String expectedMessage = "Mixing the immutable stew we find: 1 potatoes, " + + "2 carrots, 3 meat and 4 peppers"; final InOrder inOrder = inOrder(getStdOutMock()); for (int i = 0; i < 20; i++) { diff --git a/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ConsumerTest.java b/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ConsumerTest.java index e7b60a06..4ff203d4 100644 --- a/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ConsumerTest.java +++ b/producer-consumer/src/test/java/com/iluwatar/producer/consumer/ConsumerTest.java @@ -30,7 +30,7 @@ public void testConsume() throws Exception { for (int id = 0; id < ITEM_COUNT; id++) { consumer.consume(); inOrder.verify(getStdOutMock()) - .println("Consumer [consumer] consume item [" + id + "] produced by [producer]"); + .println("Consumer [consumer] consume item [" + id + "] produced by [producer]"); } inOrder.verifyNoMoreInteractions(); diff --git a/proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java b/proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java index f4deb192..dcde88f8 100644 --- a/proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java +++ b/proxy/src/test/java/com/iluwatar/proxy/WizardTowerProxyTest.java @@ -15,10 +15,10 @@ public class WizardTowerProxyTest extends StdOutTest { @Test public void testEnter() throws Exception { final Wizard[] wizards = new Wizard[]{ - new Wizard("Gandalf"), - new Wizard("Dumbledore"), - new Wizard("Oz"), - new Wizard("Merlin") + new Wizard("Gandalf"), + new Wizard("Dumbledore"), + new Wizard("Oz"), + new Wizard("Merlin") }; final WizardTowerProxy tower = new WizardTowerProxy(); diff --git a/proxy/src/test/java/com/iluwatar/proxy/WizardTowerTest.java b/proxy/src/test/java/com/iluwatar/proxy/WizardTowerTest.java index 5ddb7dda..007b92a3 100644 --- a/proxy/src/test/java/com/iluwatar/proxy/WizardTowerTest.java +++ b/proxy/src/test/java/com/iluwatar/proxy/WizardTowerTest.java @@ -15,10 +15,10 @@ public class WizardTowerTest extends StdOutTest { @Test public void testEnter() throws Exception { final Wizard[] wizards = new Wizard[]{ - new Wizard("Gandalf"), - new Wizard("Dumbledore"), - new Wizard("Oz"), - new Wizard("Merlin") + new Wizard("Gandalf"), + new Wizard("Dumbledore"), + new Wizard("Oz"), + new Wizard("Merlin") }; final WizardTower tower = new WizardTower(); diff --git a/service-locator/src/test/java/com/iluwatar/servicelocator/ServiceLocatorTest.java b/service-locator/src/test/java/com/iluwatar/servicelocator/ServiceLocatorTest.java index e50dbe02..ce54e054 100644 --- a/service-locator/src/test/java/com/iluwatar/servicelocator/ServiceLocatorTest.java +++ b/service-locator/src/test/java/com/iluwatar/servicelocator/ServiceLocatorTest.java @@ -2,7 +2,11 @@ import org.junit.Test; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; /** * Date: 12/29/15 - 19:07 PM @@ -26,7 +30,7 @@ public void testGetNonExistentService() { @Test public void testServiceCache() { final String[] serviceNames = new String[]{ - "jndi/serviceA", "jndi/serviceB" + "jndi/serviceA", "jndi/serviceB" }; for (final String serviceName : serviceNames) { diff --git a/state/src/test/java/com/iluwatar/state/AppTest.java b/state/src/test/java/com/iluwatar/state/AppTest.java index 37422e4e..d0359273 100644 --- a/state/src/test/java/com/iluwatar/state/AppTest.java +++ b/state/src/test/java/com/iluwatar/state/AppTest.java @@ -1,17 +1,15 @@ package com.iluwatar.state; -import org.junit.Ignore; import org.junit.Test; /** - * + * * Application test * */ public class AppTest { @Test - @Ignore public void test() { String[] args = {}; App.main(args); From 6326c1742d4b52d99b79495e598e657e58517f31 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Tue, 29 Dec 2015 22:19:30 +0100 Subject: [PATCH 20/26] Added tests for step-builder pattern --- .../stepbuilder/CharacterStepBuilderTest.java | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 step-builder/src/test/java/com/iluwatar/stepbuilder/CharacterStepBuilderTest.java diff --git a/step-builder/src/test/java/com/iluwatar/stepbuilder/CharacterStepBuilderTest.java b/step-builder/src/test/java/com/iluwatar/stepbuilder/CharacterStepBuilderTest.java new file mode 100644 index 00000000..b2663541 --- /dev/null +++ b/step-builder/src/test/java/com/iluwatar/stepbuilder/CharacterStepBuilderTest.java @@ -0,0 +1,155 @@ +package com.iluwatar.stepbuilder; + +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +/** + * Date: 12/29/15 - 9:21 PM + * + * @author Jeroen Meulemeester + */ +public class CharacterStepBuilderTest { + + /** + * Build a new wizard {@link Character} and verify if it has the expected attributes + */ + @Test + public void testBuildWizard() { + final Character character = CharacterStepBuilder.newBuilder() + .name("Merlin") + .wizardClass("alchemist") + .withSpell("poison") + .withAbility("invisibility") + .withAbility("wisdom") + .noMoreAbilities() + .build(); + + assertEquals("Merlin", character.getName()); + assertEquals("alchemist", character.getWizardClass()); + assertEquals("poison", character.getSpell()); + assertNotNull(character.toString()); + + final List abilities = character.getAbilities(); + assertNotNull(abilities); + assertEquals(2, abilities.size()); + assertTrue(abilities.contains("invisibility")); + assertTrue(abilities.contains("wisdom")); + + } + + /** + * Build a new wizard {@link Character} without spell or abilities and verify if it has the + * expected attributes + */ + @Test + public void testBuildPoorWizard() { + final Character character = CharacterStepBuilder.newBuilder() + .name("Merlin") + .wizardClass("alchemist") + .noSpell() + .build(); + + assertEquals("Merlin", character.getName()); + assertEquals("alchemist", character.getWizardClass()); + assertNull(character.getSpell()); + assertNull(character.getAbilities()); + assertNotNull(character.toString()); + + } + + /** + * Build a new wizard {@link Character} and verify if it has the expected attributes + */ + @Test + public void testBuildWeakWizard() { + final Character character = CharacterStepBuilder.newBuilder() + .name("Merlin") + .wizardClass("alchemist") + .withSpell("poison") + .noAbilities() + .build(); + + assertEquals("Merlin", character.getName()); + assertEquals("alchemist", character.getWizardClass()); + assertEquals("poison", character.getSpell()); + assertNull(character.getAbilities()); + assertNotNull(character.toString()); + + } + + + /** + * Build a new warrior {@link Character} and verify if it has the expected attributes + */ + @Test + public void testBuildWarrior() { + final Character character = CharacterStepBuilder.newBuilder() + .name("Cuauhtemoc") + .fighterClass("aztec") + .withWeapon("spear") + .withAbility("speed") + .withAbility("strength") + .noMoreAbilities() + .build(); + + assertEquals("Cuauhtemoc", character.getName()); + assertEquals("aztec", character.getFighterClass()); + assertEquals("spear", character.getWeapon()); + assertNotNull(character.toString()); + + final List abilities = character.getAbilities(); + assertNotNull(abilities); + assertEquals(2, abilities.size()); + assertTrue(abilities.contains("speed")); + assertTrue(abilities.contains("strength")); + + } + + /** + * Build a new wizard {@link Character} without weapon and abilities and verify if it has the + * expected attributes + */ + @Test + public void testBuildPoorWarrior() { + final Character character = CharacterStepBuilder.newBuilder() + .name("Poor warrior") + .fighterClass("none") + .noWeapon() + .build(); + + assertEquals("Poor warrior", character.getName()); + assertEquals("none", character.getFighterClass()); + assertNull(character.getWeapon()); + assertNull(character.getAbilities()); + assertNotNull(character.toString()); + + } + + /** + * Build a new warrior {@link Character} without any abilities, but with a weapon and verify if it + * has the expected attributes + */ + @Test + public void testBuildWeakWarrior() { + final Character character = CharacterStepBuilder.newBuilder() + .name("Weak warrior") + .fighterClass("none") + .withWeapon("Slingshot") + .noAbilities() + .build(); + + assertEquals("Weak warrior", character.getName()); + assertEquals("none", character.getFighterClass()); + assertEquals("Slingshot", character.getWeapon()); + assertNull(character.getAbilities()); + assertNotNull(character.toString()); + + } + +} \ No newline at end of file From 997bfba3b252d50913dd6998ed1dee2132bc4549 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Tue, 29 Dec 2015 23:06:17 +0100 Subject: [PATCH 21/26] Added tests for strategy pattern --- strategy/pom.xml | 5 + .../iluwatar/strategy/DragonSlayerTest.java | 48 ++++++++ .../strategy/DragonSlayingStrategyTest.java | 104 ++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 strategy/src/test/java/com/iluwatar/strategy/DragonSlayerTest.java create mode 100644 strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java diff --git a/strategy/pom.xml b/strategy/pom.xml index c1668277..0012775f 100644 --- a/strategy/pom.xml +++ b/strategy/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/strategy/src/test/java/com/iluwatar/strategy/DragonSlayerTest.java b/strategy/src/test/java/com/iluwatar/strategy/DragonSlayerTest.java new file mode 100644 index 00000000..907d65ac --- /dev/null +++ b/strategy/src/test/java/com/iluwatar/strategy/DragonSlayerTest.java @@ -0,0 +1,48 @@ +package com.iluwatar.strategy; + +import org.junit.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +/** + * Date: 12/29/15 - 10:50 PM + * + * @author Jeroen Meulemeester + */ +public class DragonSlayerTest { + + /** + * Verify if the dragon slayer uses the strategy during battle + */ + @Test + public void testGoToBattle() { + final DragonSlayingStrategy strategy = mock(DragonSlayingStrategy.class); + final DragonSlayer dragonSlayer = new DragonSlayer(strategy); + + dragonSlayer.goToBattle(); + verify(strategy).execute(); + verifyNoMoreInteractions(strategy); + } + + /** + * Verify if the dragon slayer uses the new strategy during battle after a change of strategy + */ + @Test + public void testChangeStrategy() throws Exception { + final DragonSlayingStrategy initialStrategy = mock(DragonSlayingStrategy.class); + final DragonSlayer dragonSlayer = new DragonSlayer(initialStrategy); + + dragonSlayer.goToBattle(); + verify(initialStrategy).execute(); + + final DragonSlayingStrategy newStrategy = mock(DragonSlayingStrategy.class); + dragonSlayer.changeStrategy(newStrategy); + + dragonSlayer.goToBattle(); + verify(newStrategy).execute(); + + verifyNoMoreInteractions(initialStrategy, newStrategy); + } +} \ No newline at end of file diff --git a/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java b/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java new file mode 100644 index 00000000..f9d18e22 --- /dev/null +++ b/strategy/src/test/java/com/iluwatar/strategy/DragonSlayingStrategyTest.java @@ -0,0 +1,104 @@ +package com.iluwatar.strategy; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.io.PrintStream; +import java.util.Arrays; +import java.util.Collection; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +/** + * Date: 12/29/15 - 10:58 PM + * + * @author Jeroen Meulemeester + */ +@RunWith(Parameterized.class) +public class DragonSlayingStrategyTest { + + /** + * @return The test parameters for each cycle + */ + @Parameterized.Parameters + public static Collection data() { + return Arrays.asList( + new Object[]{ + new MeleeStrategy(), + "With your Excalibur you severe the dragon's head!" + }, + new Object[]{ + new ProjectileStrategy(), + "You shoot the dragon with the magical crossbow and it falls dead on the ground!" + }, + new Object[]{ + new SpellStrategy(), + "You cast the spell of disintegration and the dragon vaporizes in a pile of dust!" + } + ); + } + + /** + * The tested strategy + */ + private final DragonSlayingStrategy strategy; + + /** + * The expected action on the std-out + */ + private final String expectedResult; + + /** + * The mocked standard out {@link PrintStream}, required since some actions don't have any + * influence on accessible objects, except for writing to std-out using {@link System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Create a new test instance for the given strategy + * + * @param strategy The tested strategy + * @param expectedResult The expected result + */ + public DragonSlayingStrategyTest(final DragonSlayingStrategy strategy, final String expectedResult) { + this.strategy = strategy; + this.expectedResult = expectedResult; + } + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Test if executing the strategy gives the correct response + */ + @Test + public void testExecute() { + this.strategy.execute(); + verify(this.stdOutMock).println(this.expectedResult); + verifyNoMoreInteractions(this.stdOutMock); + } + +} \ No newline at end of file From 09d3a8288472e6e3ae4561134a619d61cb4d83b3 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Wed, 30 Dec 2015 19:48:26 +0100 Subject: [PATCH 22/26] Added tests for visitor pattern --- visitor/pom.xml | 5 ++ .../com/iluwatar/visitor/CommanderTest.java | 25 ++++++ .../visitor/CommanderVisitorTest.java | 24 ++++++ .../com/iluwatar/visitor/SergeantTest.java | 25 ++++++ .../iluwatar/visitor/SergeantVisitorTest.java | 24 ++++++ .../com/iluwatar/visitor/SoldierTest.java | 25 ++++++ .../iluwatar/visitor/SoldierVisitorTest.java | 24 ++++++ .../java/com/iluwatar/visitor/StdOutTest.java | 53 ++++++++++++ .../java/com/iluwatar/visitor/UnitTest.java | 60 ++++++++++++++ .../com/iluwatar/visitor/VisitorTest.java | 80 +++++++++++++++++++ 10 files changed, 345 insertions(+) create mode 100644 visitor/src/test/java/com/iluwatar/visitor/CommanderTest.java create mode 100644 visitor/src/test/java/com/iluwatar/visitor/CommanderVisitorTest.java create mode 100644 visitor/src/test/java/com/iluwatar/visitor/SergeantTest.java create mode 100644 visitor/src/test/java/com/iluwatar/visitor/SergeantVisitorTest.java create mode 100644 visitor/src/test/java/com/iluwatar/visitor/SoldierTest.java create mode 100644 visitor/src/test/java/com/iluwatar/visitor/SoldierVisitorTest.java create mode 100644 visitor/src/test/java/com/iluwatar/visitor/StdOutTest.java create mode 100644 visitor/src/test/java/com/iluwatar/visitor/UnitTest.java create mode 100644 visitor/src/test/java/com/iluwatar/visitor/VisitorTest.java diff --git a/visitor/pom.xml b/visitor/pom.xml index c51b4a7f..b27b1da5 100644 --- a/visitor/pom.xml +++ b/visitor/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/visitor/src/test/java/com/iluwatar/visitor/CommanderTest.java b/visitor/src/test/java/com/iluwatar/visitor/CommanderTest.java new file mode 100644 index 00000000..bbf6c796 --- /dev/null +++ b/visitor/src/test/java/com/iluwatar/visitor/CommanderTest.java @@ -0,0 +1,25 @@ +package com.iluwatar.visitor; + +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.verify; + +/** + * Date: 12/30/15 - 19:45 PM + * + * @author Jeroen Meulemeester + */ +public class CommanderTest extends UnitTest { + + /** + * Create a new test instance for the given {@link Commander} + */ + public CommanderTest() { + super(Commander::new); + } + + @Override + void verifyVisit(Commander unit, UnitVisitor mockedVisitor) { + verify(mockedVisitor).visitCommander(eq(unit)); + } + +} \ No newline at end of file diff --git a/visitor/src/test/java/com/iluwatar/visitor/CommanderVisitorTest.java b/visitor/src/test/java/com/iluwatar/visitor/CommanderVisitorTest.java new file mode 100644 index 00000000..ac296c33 --- /dev/null +++ b/visitor/src/test/java/com/iluwatar/visitor/CommanderVisitorTest.java @@ -0,0 +1,24 @@ +package com.iluwatar.visitor; + +import java.util.Optional; + +/** + * Date: 12/30/15 - 18:43 PM + * + * @author Jeroen Meulemeester + */ +public class CommanderVisitorTest extends VisitorTest { + + /** + * Create a new test instance for the given visitor + */ + public CommanderVisitorTest() { + super( + new CommanderVisitor(), + Optional.of("Good to see you commander"), + Optional.empty(), + Optional.empty() + ); + } + +} diff --git a/visitor/src/test/java/com/iluwatar/visitor/SergeantTest.java b/visitor/src/test/java/com/iluwatar/visitor/SergeantTest.java new file mode 100644 index 00000000..d0e6d3db --- /dev/null +++ b/visitor/src/test/java/com/iluwatar/visitor/SergeantTest.java @@ -0,0 +1,25 @@ +package com.iluwatar.visitor; + +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.verify; + +/** + * Date: 12/30/15 - 19:45 PM + * + * @author Jeroen Meulemeester + */ +public class SergeantTest extends UnitTest { + + /** + * Create a new test instance for the given {@link Sergeant} + */ + public SergeantTest() { + super(Sergeant::new); + } + + @Override + void verifyVisit(Sergeant unit, UnitVisitor mockedVisitor) { + verify(mockedVisitor).visitSergeant(eq(unit)); + } + +} \ No newline at end of file diff --git a/visitor/src/test/java/com/iluwatar/visitor/SergeantVisitorTest.java b/visitor/src/test/java/com/iluwatar/visitor/SergeantVisitorTest.java new file mode 100644 index 00000000..54e274bc --- /dev/null +++ b/visitor/src/test/java/com/iluwatar/visitor/SergeantVisitorTest.java @@ -0,0 +1,24 @@ +package com.iluwatar.visitor; + +import java.util.Optional; + +/** + * Date: 12/30/15 - 18:36 PM + * + * @author Jeroen Meulemeester + */ +public class SergeantVisitorTest extends VisitorTest { + + /** + * Create a new test instance for the given visitor + */ + public SergeantVisitorTest() { + super( + new SergeantVisitor(), + Optional.empty(), + Optional.of("Hello sergeant"), + Optional.empty() + ); + } + +} diff --git a/visitor/src/test/java/com/iluwatar/visitor/SoldierTest.java b/visitor/src/test/java/com/iluwatar/visitor/SoldierTest.java new file mode 100644 index 00000000..e9aa5460 --- /dev/null +++ b/visitor/src/test/java/com/iluwatar/visitor/SoldierTest.java @@ -0,0 +1,25 @@ +package com.iluwatar.visitor; + +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.verify; + +/** + * Date: 12/30/15 - 19:45 PM + * + * @author Jeroen Meulemeester + */ +public class SoldierTest extends UnitTest { + + /** + * Create a new test instance for the given {@link Soldier} + */ + public SoldierTest() { + super(Soldier::new); + } + + @Override + void verifyVisit(Soldier unit, UnitVisitor mockedVisitor) { + verify(mockedVisitor).visitSoldier(eq(unit)); + } + +} \ No newline at end of file diff --git a/visitor/src/test/java/com/iluwatar/visitor/SoldierVisitorTest.java b/visitor/src/test/java/com/iluwatar/visitor/SoldierVisitorTest.java new file mode 100644 index 00000000..a5f16e9e --- /dev/null +++ b/visitor/src/test/java/com/iluwatar/visitor/SoldierVisitorTest.java @@ -0,0 +1,24 @@ +package com.iluwatar.visitor; + +import java.util.Optional; + +/** + * Date: 12/30/15 - 18:59 PM + * + * @author Jeroen Meulemeester + */ +public class SoldierVisitorTest extends VisitorTest { + + /** + * Create a new test instance for the given visitor + */ + public SoldierVisitorTest() { + super( + new SoldierVisitor(), + Optional.empty(), + Optional.empty(), + Optional.of("Greetings soldier") + ); + } + +} diff --git a/visitor/src/test/java/com/iluwatar/visitor/StdOutTest.java b/visitor/src/test/java/com/iluwatar/visitor/StdOutTest.java new file mode 100644 index 00000000..2c54994b --- /dev/null +++ b/visitor/src/test/java/com/iluwatar/visitor/StdOutTest.java @@ -0,0 +1,53 @@ +package com.iluwatar.visitor; + +import org.junit.After; +import org.junit.Before; + +import java.io.PrintStream; + +import static org.mockito.Mockito.mock; + +/** + * Date: 12/10/15 - 8:37 PM + * + * @author Jeroen Meulemeester + */ +public abstract class StdOutTest { + + /** + * The mocked standard out {@link PrintStream}, required since some actions don't have any + * influence on accessible objects, except for writing to std-out using {@link System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Get the mocked stdOut {@link PrintStream} + * + * @return The stdOut print stream mock, renewed before each test + */ + final PrintStream getStdOutMock() { + return this.stdOutMock; + } + +} diff --git a/visitor/src/test/java/com/iluwatar/visitor/UnitTest.java b/visitor/src/test/java/com/iluwatar/visitor/UnitTest.java new file mode 100644 index 00000000..291ab544 --- /dev/null +++ b/visitor/src/test/java/com/iluwatar/visitor/UnitTest.java @@ -0,0 +1,60 @@ +package com.iluwatar.visitor; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.function.Function; + +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +/** + * Date: 12/30/15 - 18:59 PM + * + * @author Jeroen Meulemeester + */ +public abstract class UnitTest { + + /** + * Factory to create new instances of the tested unit + */ + private final Function factory; + + /** + * Create a new test instance for the given unit type {@link U} + * + * @param factory Factory to create new instances of the tested unit + */ + public UnitTest(final Function factory) { + this.factory = factory; + } + + @Test + public void testAccept() throws Exception { + final Unit[] children = new Unit[5]; + Arrays.setAll(children, (i) -> mock(Unit.class)); + + final U unit = this.factory.apply(children); + final UnitVisitor visitor = mock(UnitVisitor.class); + unit.accept(visitor); + verifyVisit(unit, visitor); + + for (final Unit child : children) { + verify(child).accept(eq(visitor)); + } + + verifyNoMoreInteractions(children); + verifyNoMoreInteractions(visitor); + } + + /** + * Verify if the correct visit method is called on the mock, depending on the tested instance + * + * @param unit The tested unit instance + * @param mockedVisitor The mocked {@link UnitVisitor} who should have gotten a visit by the unit + */ + abstract void verifyVisit(final U unit, final UnitVisitor mockedVisitor); + +} \ No newline at end of file diff --git a/visitor/src/test/java/com/iluwatar/visitor/VisitorTest.java b/visitor/src/test/java/com/iluwatar/visitor/VisitorTest.java new file mode 100644 index 00000000..7bd9f03c --- /dev/null +++ b/visitor/src/test/java/com/iluwatar/visitor/VisitorTest.java @@ -0,0 +1,80 @@ +package com.iluwatar.visitor; + +import org.junit.Test; + +import java.util.Optional; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +/** + * Date: 12/30/15 - 18:59 PM + * + * @author Jeroen Meulemeester + */ +public abstract class VisitorTest extends StdOutTest { + + /** + * The tested visitor instance + */ + private final V visitor; + + /** + * The optional expected response when being visited by a commander + */ + private final Optional commanderResponse; + + /** + * The optional expected response when being visited by a sergeant + */ + private final Optional sergeantResponse; + + /** + * The optional expected response when being visited by a soldier + */ + private final Optional soldierResponse; + + /** + * Create a new test instance for the given visitor + * + * @param commanderResponse The optional expected response when being visited by a commander + * @param sergeantResponse The optional expected response when being visited by a sergeant + * @param soldierResponse The optional expected response when being visited by a soldier + */ + public VisitorTest(final V visitor, final Optional commanderResponse, + final Optional sergeantResponse, final Optional soldierResponse) { + + this.visitor = visitor; + this.commanderResponse = commanderResponse; + this.sergeantResponse = sergeantResponse; + this.soldierResponse = soldierResponse; + } + + @Test + public void testVisitCommander() { + this.visitor.visitCommander(new Commander()); + if (this.commanderResponse.isPresent()) { + verify(getStdOutMock()).println(this.commanderResponse.get()); + } + verifyNoMoreInteractions(getStdOutMock()); + } + + @Test + public void testVisitSergeant() { + this.visitor.visitSergeant(new Sergeant()); + if (this.sergeantResponse.isPresent()) { + verify(getStdOutMock()).println(this.sergeantResponse.get()); + } + verifyNoMoreInteractions(getStdOutMock()); + } + + @Test + public void testVisitSoldier() { + this.visitor.visitSoldier(new Soldier()); + if (this.soldierResponse.isPresent()) { + verify(getStdOutMock()).println(this.soldierResponse.get()); + } + verifyNoMoreInteractions(getStdOutMock()); + } + +} From 47709e24b9eb7ddc6e0fb467a6c2c703f8539eb2 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Wed, 30 Dec 2015 19:48:38 +0100 Subject: [PATCH 23/26] Added tests for template-method pattern --- template-method/pom.xml | 5 + .../templatemethod/HalflingThiefTest.java | 50 ++++++ .../templatemethod/HitAndRunMethodTest.java | 23 +++ .../templatemethod/StealingMethodTest.java | 142 ++++++++++++++++++ .../templatemethod/SubtleMethodTest.java | 23 +++ 5 files changed, 243 insertions(+) create mode 100644 template-method/src/test/java/com/iluwatar/templatemethod/HalflingThiefTest.java create mode 100644 template-method/src/test/java/com/iluwatar/templatemethod/HitAndRunMethodTest.java create mode 100644 template-method/src/test/java/com/iluwatar/templatemethod/StealingMethodTest.java create mode 100644 template-method/src/test/java/com/iluwatar/templatemethod/SubtleMethodTest.java diff --git a/template-method/pom.xml b/template-method/pom.xml index 482a7c5c..f43d42e7 100644 --- a/template-method/pom.xml +++ b/template-method/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/template-method/src/test/java/com/iluwatar/templatemethod/HalflingThiefTest.java b/template-method/src/test/java/com/iluwatar/templatemethod/HalflingThiefTest.java new file mode 100644 index 00000000..be049720 --- /dev/null +++ b/template-method/src/test/java/com/iluwatar/templatemethod/HalflingThiefTest.java @@ -0,0 +1,50 @@ +package com.iluwatar.templatemethod; + +import org.junit.Test; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +/** + * Date: 12/29/15 - 18:15 PM + * + * @author Jeroen Meulemeester + */ +public class HalflingThiefTest { + + /** + * Verify if the thief uses the provided stealing method + */ + @Test + public void testSteal() { + final StealingMethod method = mock(StealingMethod.class); + final HalflingThief thief = new HalflingThief(method); + + thief.steal(); + verify(method).steal(); + + verifyNoMoreInteractions(method); + } + + /** + * Verify if the thief uses the provided stealing method, and the new method after changing it + */ + @Test + public void testChangeMethod() { + final StealingMethod initialMethod = mock(StealingMethod.class); + final HalflingThief thief = new HalflingThief(initialMethod); + + thief.steal(); + verify(initialMethod).steal(); + + final StealingMethod newMethod = mock(StealingMethod.class); + thief.changeMethod(newMethod); + + thief.steal(); + verify(newMethod).steal(); + + verifyNoMoreInteractions(initialMethod, newMethod); + + } +} \ No newline at end of file diff --git a/template-method/src/test/java/com/iluwatar/templatemethod/HitAndRunMethodTest.java b/template-method/src/test/java/com/iluwatar/templatemethod/HitAndRunMethodTest.java new file mode 100644 index 00000000..86fc2591 --- /dev/null +++ b/template-method/src/test/java/com/iluwatar/templatemethod/HitAndRunMethodTest.java @@ -0,0 +1,23 @@ +package com.iluwatar.templatemethod; + +/** + * Date: 12/30/15 - 18:12 PM + * + * @author Jeroen Meulemeester + */ +public class HitAndRunMethodTest extends StealingMethodTest { + + /** + * Create a new test for the {@link HitAndRunMethod} + */ + public HitAndRunMethodTest() { + super( + new HitAndRunMethod(), + "old goblin woman", + "The target has been chosen as old goblin woman.", + "Approach the old goblin woman from behind.", + "Grab the handbag and run away fast!" + ); + } + +} \ No newline at end of file diff --git a/template-method/src/test/java/com/iluwatar/templatemethod/StealingMethodTest.java b/template-method/src/test/java/com/iluwatar/templatemethod/StealingMethodTest.java new file mode 100644 index 00000000..61143a15 --- /dev/null +++ b/template-method/src/test/java/com/iluwatar/templatemethod/StealingMethodTest.java @@ -0,0 +1,142 @@ +package com.iluwatar.templatemethod; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InOrder; + +import java.io.PrintStream; + +import static org.junit.Assert.assertEquals; +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/30/15 - 18:12 PM + * + * @author Jeroen Meulemeester + */ +public abstract class StealingMethodTest { + + /** + * The tested stealing method + */ + private final M method; + + /** + * The expected target + */ + private final String expectedTarget; + + /** + * The expected target picking result + */ + private final String expectedTargetResult; + + /** + * The expected confusion method + */ + private final String expectedConfuseMethod; + + /** + * The expected stealing method + */ + private final String expectedStealMethod; + + /** + * The mocked standard out {@link PrintStream}, required since some actions don't have any + * influence on accessible objects, except for writing to std-out using {@link System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Create a new test for the given stealing method, together with the expected results + * + * @param method The tested stealing method + * @param expectedTarget The expected target name + * @param expectedTargetResult The expected target picking result + * @param expectedConfuseMethod The expected confusion method + * @param expectedStealMethod The expected stealing method + */ + public StealingMethodTest(final M method, String expectedTarget, final String expectedTargetResult, + final String expectedConfuseMethod, final String expectedStealMethod) { + + this.method = method; + this.expectedTarget = expectedTarget; + this.expectedTargetResult = expectedTargetResult; + this.expectedConfuseMethod = expectedConfuseMethod; + this.expectedStealMethod = expectedStealMethod; + } + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Verify if the thief picks the correct target + */ + @Test + public void testPickTarget() { + assertEquals(expectedTarget, this.method.pickTarget()); + } + + /** + * Verify if the target confusing step goes as planned + */ + @Test + public void testConfuseTarget() { + verifyZeroInteractions(this.stdOutMock); + + this.method.confuseTarget(this.expectedTarget); + verify(this.stdOutMock).println(this.expectedConfuseMethod); + verifyNoMoreInteractions(this.stdOutMock); + } + + /** + * Verify if the stealing step goes as planned + */ + @Test + public void testStealTheItem() { + verifyZeroInteractions(this.stdOutMock); + + this.method.stealTheItem(this.expectedTarget); + verify(this.stdOutMock).println(this.expectedStealMethod); + verifyNoMoreInteractions(this.stdOutMock); + } + + /** + * Verify if the complete steal process goes as planned + */ + @Test + public void testSteal() { + final InOrder inOrder = inOrder(this.stdOutMock); + + this.method.steal(); + + inOrder.verify(this.stdOutMock).println(this.expectedTargetResult); + inOrder.verify(this.stdOutMock).println(this.expectedConfuseMethod); + inOrder.verify(this.stdOutMock).println(this.expectedStealMethod); + inOrder.verifyNoMoreInteractions(); + } + +} \ No newline at end of file diff --git a/template-method/src/test/java/com/iluwatar/templatemethod/SubtleMethodTest.java b/template-method/src/test/java/com/iluwatar/templatemethod/SubtleMethodTest.java new file mode 100644 index 00000000..8b3681a7 --- /dev/null +++ b/template-method/src/test/java/com/iluwatar/templatemethod/SubtleMethodTest.java @@ -0,0 +1,23 @@ +package com.iluwatar.templatemethod; + +/** + * Date: 12/30/15 - 18:19 PM + * + * @author Jeroen Meulemeester + */ +public class SubtleMethodTest extends StealingMethodTest { + + /** + * Create a new test for the {@link SubtleMethod} + */ + public SubtleMethodTest() { + super( + new SubtleMethod(), + "shop keeper", + "The target has been chosen as shop keeper.", + "Approach the shop keeper with tears running and hug him!", + "While in close contact grab the shop keeper's wallet." + ); + } + +} \ No newline at end of file From fd8c05846f9cca82dbc49c0da3c405699515a73b Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Wed, 30 Dec 2015 19:49:47 +0100 Subject: [PATCH 24/26] Added tests for thread-pool pattern Fixed concurrency problem in id generation of Task --- thread-pool/pom.xml | 5 + .../iluwatar/threadpool/CoffeeMakingTask.java | 2 +- .../threadpool/PotatoPeelingTask.java | 2 +- .../java/com/iluwatar/threadpool/Task.java | 8 +- .../threadpool/CoffeeMakingTaskTest.java | 17 +++ .../threadpool/PotatoPeelingTaskTest.java | 17 +++ .../com/iluwatar/threadpool/TaskTest.java | 121 ++++++++++++++++++ .../com/iluwatar/threadpool/WorkerTest.java | 31 +++++ 8 files changed, 198 insertions(+), 5 deletions(-) create mode 100644 thread-pool/src/test/java/com/iluwatar/threadpool/CoffeeMakingTaskTest.java create mode 100644 thread-pool/src/test/java/com/iluwatar/threadpool/PotatoPeelingTaskTest.java create mode 100644 thread-pool/src/test/java/com/iluwatar/threadpool/TaskTest.java create mode 100644 thread-pool/src/test/java/com/iluwatar/threadpool/WorkerTest.java diff --git a/thread-pool/pom.xml b/thread-pool/pom.xml index c5014023..ed6f8f7f 100644 --- a/thread-pool/pom.xml +++ b/thread-pool/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/thread-pool/src/main/java/com/iluwatar/threadpool/CoffeeMakingTask.java b/thread-pool/src/main/java/com/iluwatar/threadpool/CoffeeMakingTask.java index f1247101..3a846409 100644 --- a/thread-pool/src/main/java/com/iluwatar/threadpool/CoffeeMakingTask.java +++ b/thread-pool/src/main/java/com/iluwatar/threadpool/CoffeeMakingTask.java @@ -7,7 +7,7 @@ */ public class CoffeeMakingTask extends Task { - private static final int TIME_PER_CUP = 300; + private static final int TIME_PER_CUP = 100; public CoffeeMakingTask(int numCups) { super(numCups * TIME_PER_CUP); diff --git a/thread-pool/src/main/java/com/iluwatar/threadpool/PotatoPeelingTask.java b/thread-pool/src/main/java/com/iluwatar/threadpool/PotatoPeelingTask.java index a90bf4be..2be94140 100644 --- a/thread-pool/src/main/java/com/iluwatar/threadpool/PotatoPeelingTask.java +++ b/thread-pool/src/main/java/com/iluwatar/threadpool/PotatoPeelingTask.java @@ -7,7 +7,7 @@ */ public class PotatoPeelingTask extends Task { - private static final int TIME_PER_POTATO = 500; + private static final int TIME_PER_POTATO = 200; public PotatoPeelingTask(int numPotatoes) { super(numPotatoes * TIME_PER_POTATO); diff --git a/thread-pool/src/main/java/com/iluwatar/threadpool/Task.java b/thread-pool/src/main/java/com/iluwatar/threadpool/Task.java index 12fecbbd..2426948b 100644 --- a/thread-pool/src/main/java/com/iluwatar/threadpool/Task.java +++ b/thread-pool/src/main/java/com/iluwatar/threadpool/Task.java @@ -1,19 +1,21 @@ package com.iluwatar.threadpool; +import java.util.concurrent.atomic.AtomicInteger; + /** - * + * * Abstract base class for tasks * */ public abstract class Task { - private static int nextId = 1; + private static final AtomicInteger ID_GENERATOR = new AtomicInteger(); private final int id; private final int timeMs; public Task(final int timeMs) { - this.id = nextId++; + this.id = ID_GENERATOR.incrementAndGet(); this.timeMs = timeMs; } diff --git a/thread-pool/src/test/java/com/iluwatar/threadpool/CoffeeMakingTaskTest.java b/thread-pool/src/test/java/com/iluwatar/threadpool/CoffeeMakingTaskTest.java new file mode 100644 index 00000000..ab3d47d9 --- /dev/null +++ b/thread-pool/src/test/java/com/iluwatar/threadpool/CoffeeMakingTaskTest.java @@ -0,0 +1,17 @@ +package com.iluwatar.threadpool; + +/** + * Date: 12/30/15 - 18:23 PM + * + * @author Jeroen Meulemeester + */ +public class CoffeeMakingTaskTest extends TaskTest { + + /** + * Create a new test instance + */ + public CoffeeMakingTaskTest() { + super(CoffeeMakingTask::new, 100); + } + +} diff --git a/thread-pool/src/test/java/com/iluwatar/threadpool/PotatoPeelingTaskTest.java b/thread-pool/src/test/java/com/iluwatar/threadpool/PotatoPeelingTaskTest.java new file mode 100644 index 00000000..4f9b1496 --- /dev/null +++ b/thread-pool/src/test/java/com/iluwatar/threadpool/PotatoPeelingTaskTest.java @@ -0,0 +1,17 @@ +package com.iluwatar.threadpool; + +/** + * Date: 12/30/15 - 18:23 PM + * + * @author Jeroen Meulemeester + */ +public class PotatoPeelingTaskTest extends TaskTest { + + /** + * Create a new test instance + */ + public PotatoPeelingTaskTest() { + super(PotatoPeelingTask::new, 200); + } + +} \ No newline at end of file diff --git a/thread-pool/src/test/java/com/iluwatar/threadpool/TaskTest.java b/thread-pool/src/test/java/com/iluwatar/threadpool/TaskTest.java new file mode 100644 index 00000000..f1ef8160 --- /dev/null +++ b/thread-pool/src/test/java/com/iluwatar/threadpool/TaskTest.java @@ -0,0 +1,121 @@ +package com.iluwatar.threadpool; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Date: 12/30/15 - 18:22 PM + * + * @author Jeroen Meulemeester + */ +public abstract class TaskTest { + + /** + * The number of tasks used during the concurrency test + */ + private static final int TASK_COUNT = 128 * 1024; + + /** + * The number of threads used during the concurrency test + */ + private static final int THREAD_COUNT = 8; + + /** + * The task factory, used to create new test items + */ + private final Function factory; + + /** + * The expected time needed to run the task 1 single time, in milli seconds + */ + private final int expectedExecutionTime; + + /** + * Create a new test instance + * + * @param factory The task factory, used to create new test items + * @param expectedExecutionTime The expected time needed to run the task 1 time, in milli seconds + */ + public TaskTest(final Function factory, final int expectedExecutionTime) { + this.factory = factory; + this.expectedExecutionTime = expectedExecutionTime; + } + + /** + * Verify if the generated id is unique for each task, even if the tasks are created in separate + * threads + */ + @Test(timeout = 10000) + public void testIdGeneration() throws Exception { + final ExecutorService service = Executors.newFixedThreadPool(THREAD_COUNT); + + final List> tasks = new ArrayList<>(); + for (int i = 0; i < TASK_COUNT; i++) { + tasks.add(() -> factory.apply(1).getId()); + } + + final List ids = service.invokeAll(tasks) + .stream() + .map(TaskTest::get) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + + service.shutdownNow(); + + final long uniqueIdCount = ids.stream() + .distinct() + .count(); + + assertEquals(TASK_COUNT, ids.size()); + assertEquals(TASK_COUNT, uniqueIdCount); + + } + + /** + * Verify if the time per execution of a task matches the actual time required to execute the task + * a given number of times + */ + @Test + public void testTimeMs() { + for (int i = 0; i < 10; i++) { + assertEquals(this.expectedExecutionTime * i, this.factory.apply(i).getTimeMs()); + } + } + + /** + * Verify if the task has some sort of {@link T#toString()}, different from 'null' + */ + @Test + public void testToString() { + assertNotNull(this.factory.apply(0).toString()); + } + + /** + * Extract the result from a future or returns 'null' when an exception occurred + * + * @param future The future we want the result from + * @param The result type + * @return The result or 'null' when a checked exception occurred + */ + private static O get(Future future) { + try { + return future.get(); + } catch (InterruptedException | ExecutionException e) { + return null; + } + } + +} \ No newline at end of file diff --git a/thread-pool/src/test/java/com/iluwatar/threadpool/WorkerTest.java b/thread-pool/src/test/java/com/iluwatar/threadpool/WorkerTest.java new file mode 100644 index 00000000..53a1d869 --- /dev/null +++ b/thread-pool/src/test/java/com/iluwatar/threadpool/WorkerTest.java @@ -0,0 +1,31 @@ +package com.iluwatar.threadpool; + +import org.junit.Test; + +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/30/15 - 18:21 PM + * + * @author Jeroen Meulemeester + */ +public class WorkerTest { + + /** + * Verify if a worker does the actual job + */ + @Test + public void testRun() { + final Task task = mock(Task.class); + final Worker worker = new Worker(task); + verifyZeroInteractions(task); + + worker.run(); + verify(task).getTimeMs(); + verifyNoMoreInteractions(task); + } + +} \ No newline at end of file From 444eb07e26223e2e56aee6a6ad252816a37e00c9 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Wed, 30 Dec 2015 19:49:56 +0100 Subject: [PATCH 25/26] Added tests for tolerant-reader pattern --- .../RainbowFishSerializerTest.java | 68 +++++++++++++++++++ .../tolerantreader/RainbowFishTest.java | 26 +++++++ .../tolerantreader/RainbowFishV2Test.java | 29 ++++++++ 3 files changed, 123 insertions(+) create mode 100644 tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishSerializerTest.java create mode 100644 tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishTest.java create mode 100644 tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishV2Test.java diff --git a/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishSerializerTest.java b/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishSerializerTest.java new file mode 100644 index 00000000..5f7ca026 --- /dev/null +++ b/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishSerializerTest.java @@ -0,0 +1,68 @@ +package com.iluwatar.tolerantreader; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; + +/** + * Date: 12/30/15 - 18:39 PM + * + * @author Jeroen Meulemeester + */ +public class RainbowFishSerializerTest { + + /** + * Create a temporary folder, used to generate files in during this test + */ + @Rule + public final TemporaryFolder testFolder = new TemporaryFolder(); + + /** + * Rainbow fish version 1 used during the tests + */ + private static final RainbowFish V1 = new RainbowFish("version1", 1, 2, 3); + + /** + * Rainbow fish version 2 used during the tests + */ + private static final RainbowFishV2 V2 = new RainbowFishV2("version2", 4, 5, 6, true, false, true); + + /** + * Verify if a fish, written as version 1 can be read back as version 1 + */ + @Test + public void testWriteV1ReadV1() throws Exception { + final File outputFile = this.testFolder.newFile(); + RainbowFishSerializer.writeV1(V1, outputFile.getPath()); + + final RainbowFish fish = RainbowFishSerializer.readV1(outputFile.getPath()); + assertNotSame(V1, fish); + assertEquals(V1.getName(), fish.getName()); + assertEquals(V1.getAge(), fish.getAge()); + assertEquals(V1.getLengthMeters(), fish.getLengthMeters()); + assertEquals(V1.getWeightTons(), fish.getWeightTons()); + + } + + /** + * Verify if a fish, written as version 2 can be read back as version 1 + */ + @Test + public void testWriteV2ReadV1() throws Exception { + final File outputFile = this.testFolder.newFile(); + RainbowFishSerializer.writeV2(V2, outputFile.getPath()); + + final RainbowFish fish = RainbowFishSerializer.readV1(outputFile.getPath()); + assertNotSame(V2, fish); + assertEquals(V2.getName(), fish.getName()); + assertEquals(V2.getAge(), fish.getAge()); + assertEquals(V2.getLengthMeters(), fish.getLengthMeters()); + assertEquals(V2.getWeightTons(), fish.getWeightTons()); + } + +} \ No newline at end of file diff --git a/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishTest.java b/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishTest.java new file mode 100644 index 00000000..0f7df25c --- /dev/null +++ b/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishTest.java @@ -0,0 +1,26 @@ +package com.iluwatar.tolerantreader; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Date: 12/30/15 - 18:34 PM + * + * @author Jeroen Meulemeester + */ +public class RainbowFishTest { + + /** + * Verify if the getters of a {@link RainbowFish} return the expected values + */ + @Test + public void testValues() { + final RainbowFish fish = new RainbowFish("name", 1, 2, 3); + assertEquals("name", fish.getName()); + assertEquals(1, fish.getAge()); + assertEquals(2, fish.getLengthMeters()); + assertEquals(3, fish.getWeightTons()); + } + +} \ No newline at end of file diff --git a/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishV2Test.java b/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishV2Test.java new file mode 100644 index 00000000..5e8bdcef --- /dev/null +++ b/tolerant-reader/src/test/java/com/iluwatar/tolerantreader/RainbowFishV2Test.java @@ -0,0 +1,29 @@ +package com.iluwatar.tolerantreader; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +/** + * Date: 12/30/15 - 18:35 PM + * + * @author Jeroen Meulemeester + */ +public class RainbowFishV2Test { + + /** + * Verify if the getters of a {@link RainbowFish} return the expected values + */ + @Test + public void testValues() { + final RainbowFishV2 fish = new RainbowFishV2("name", 1, 2, 3, false, true, false); + assertEquals("name", fish.getName()); + assertEquals(1, fish.getAge()); + assertEquals(2, fish.getLengthMeters()); + assertEquals(3, fish.getWeightTons()); + assertEquals(false, fish.getSleeping()); + assertEquals(true, fish.getHungry()); + assertEquals(false, fish.getAngry()); + } + +} \ No newline at end of file From 542a832a66aca547604659a6c03fd037d51b6a04 Mon Sep 17 00:00:00 2001 From: Jeroen Meulemeester Date: Wed, 30 Dec 2015 19:50:07 +0100 Subject: [PATCH 26/26] Added tests for twin pattern --- twin/pom.xml | 5 ++ twin/src/main/java/com/iluwatar/twin/App.java | 2 +- .../java/com/iluwatar/twin/BallThread.java | 13 ++- .../java/com/iluwatar/twin/BallItemTest.java | 62 +++++++++++++ .../com/iluwatar/twin/BallThreadTest.java | 89 +++++++++++++++++++ .../java/com/iluwatar/twin/StdOutTest.java | 53 +++++++++++ 6 files changed, 216 insertions(+), 8 deletions(-) create mode 100644 twin/src/test/java/com/iluwatar/twin/BallItemTest.java create mode 100644 twin/src/test/java/com/iluwatar/twin/BallThreadTest.java create mode 100644 twin/src/test/java/com/iluwatar/twin/StdOutTest.java diff --git a/twin/pom.xml b/twin/pom.xml index 95e94249..7f764f53 100644 --- a/twin/pom.xml +++ b/twin/pom.xml @@ -14,5 +14,10 @@ junit test + + org.mockito + mockito-core + test + diff --git a/twin/src/main/java/com/iluwatar/twin/App.java b/twin/src/main/java/com/iluwatar/twin/App.java index eaa21a84..cb971c49 100644 --- a/twin/src/main/java/com/iluwatar/twin/App.java +++ b/twin/src/main/java/com/iluwatar/twin/App.java @@ -41,6 +41,6 @@ public static void main(String[] args) throws Exception { } private static void waiting() throws Exception { - Thread.sleep(2500); + Thread.sleep(750); } } diff --git a/twin/src/main/java/com/iluwatar/twin/BallThread.java b/twin/src/main/java/com/iluwatar/twin/BallThread.java index e165782a..2d9e7c41 100644 --- a/twin/src/main/java/com/iluwatar/twin/BallThread.java +++ b/twin/src/main/java/com/iluwatar/twin/BallThread.java @@ -25,15 +25,14 @@ public void setTwin(BallItem twin) { public void run() { while (isRunning) { - while (!isSuspended) { + if (!isSuspended) { twin.draw(); twin.move(); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - + } + try { + Thread.sleep(250); + } catch (InterruptedException e) { + throw new RuntimeException(e); } } } diff --git a/twin/src/test/java/com/iluwatar/twin/BallItemTest.java b/twin/src/test/java/com/iluwatar/twin/BallItemTest.java new file mode 100644 index 00000000..ca1da7ac --- /dev/null +++ b/twin/src/test/java/com/iluwatar/twin/BallItemTest.java @@ -0,0 +1,62 @@ +package com.iluwatar.twin; + +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; + +/** + * Date: 12/30/15 - 18:44 PM + * + * @author Jeroen Meulemeester + */ +public class BallItemTest extends StdOutTest { + + @Test + public void testClick() { + final BallThread ballThread = mock(BallThread.class); + final BallItem ballItem = new BallItem(); + ballItem.setTwin(ballThread); + + final InOrder inOrder = inOrder(ballThread); + + for (int i = 0; i < 10; i++) { + ballItem.click(); + inOrder.verify(ballThread).suspendMe(); + + ballItem.click(); + inOrder.verify(ballThread).resumeMe(); + } + + inOrder.verifyNoMoreInteractions(); + } + + @Test + public void testDoDraw() { + final BallItem ballItem = new BallItem(); + final BallThread ballThread = mock(BallThread.class); + ballItem.setTwin(ballThread); + + ballItem.draw(); + verify(getStdOutMock()).println("draw"); + verify(getStdOutMock()).println("doDraw"); + + verifyNoMoreInteractions(ballThread, getStdOutMock()); + } + + @Test + public void testMove() { + final BallItem ballItem = new BallItem(); + final BallThread ballThread = mock(BallThread.class); + ballItem.setTwin(ballThread); + + ballItem.move(); + verify(getStdOutMock()).println("move"); + + verifyNoMoreInteractions(ballThread, getStdOutMock()); + } + +} \ No newline at end of file diff --git a/twin/src/test/java/com/iluwatar/twin/BallThreadTest.java b/twin/src/test/java/com/iluwatar/twin/BallThreadTest.java new file mode 100644 index 00000000..7e0bdc11 --- /dev/null +++ b/twin/src/test/java/com/iluwatar/twin/BallThreadTest.java @@ -0,0 +1,89 @@ +package com.iluwatar.twin; + +import org.junit.Test; + +import static java.lang.Thread.UncaughtExceptionHandler; +import static java.lang.Thread.sleep; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +/** + * Date: 12/30/15 - 18:55 PM + * + * @author Jeroen Meulemeester + */ +public class BallThreadTest { + + /** + * Verify if the {@link BallThread} can be resumed + */ + @Test(timeout = 5000) + public void testSuspend() throws Exception { + final BallThread ballThread = new BallThread(); + + final BallItem ballItem = mock(BallItem.class); + ballThread.setTwin(ballItem); + + ballThread.start(); + + verify(ballItem, timeout(2000).atLeastOnce()).draw(); + verify(ballItem, timeout(2000).atLeastOnce()).move(); + ballThread.suspendMe(); + + sleep(1000); + + ballThread.stopMe(); + ballThread.join(); + + verifyNoMoreInteractions(ballItem); + } + + /** + * Verify if the {@link BallThread} can be resumed + */ + @Test(timeout = 5000) + public void testResume() throws Exception { + final BallThread ballThread = new BallThread(); + + final BallItem ballItem = mock(BallItem.class); + ballThread.setTwin(ballItem); + + ballThread.suspendMe(); + ballThread.start(); + + sleep(1000); + + verifyZeroInteractions(ballItem); + + ballThread.resumeMe(); + verify(ballItem, timeout(2000).atLeastOnce()).draw(); + verify(ballItem, timeout(2000).atLeastOnce()).move(); + + ballThread.stopMe(); + ballThread.join(); + + verifyNoMoreInteractions(ballItem); + } + + /** + * Verify if the {@link BallThread} is interruptible + */ + @Test(timeout = 5000) + public void testInterrupt() throws Exception { + final BallThread ballThread = new BallThread(); + final UncaughtExceptionHandler exceptionHandler = mock(UncaughtExceptionHandler.class); + ballThread.setUncaughtExceptionHandler(exceptionHandler); + ballThread.setTwin(mock(BallItem.class)); + ballThread.start(); + ballThread.interrupt(); + ballThread.join(); + + verify(exceptionHandler).uncaughtException(eq(ballThread), any(RuntimeException.class)); + verifyNoMoreInteractions(exceptionHandler); + } +} \ No newline at end of file diff --git a/twin/src/test/java/com/iluwatar/twin/StdOutTest.java b/twin/src/test/java/com/iluwatar/twin/StdOutTest.java new file mode 100644 index 00000000..f506886e --- /dev/null +++ b/twin/src/test/java/com/iluwatar/twin/StdOutTest.java @@ -0,0 +1,53 @@ +package com.iluwatar.twin; + +import org.junit.After; +import org.junit.Before; + +import java.io.PrintStream; + +import static org.mockito.Mockito.mock; + +/** + * Date: 12/10/15 - 8:37 PM + * + * @author Jeroen Meulemeester + */ +public abstract class StdOutTest { + + /** + * The mocked standard out {@link PrintStream}, required since some actions don't have any + * influence on accessible objects, except for writing to std-out using {@link System#out} + */ + private final PrintStream stdOutMock = mock(PrintStream.class); + + /** + * Keep the original std-out so it can be restored after the test + */ + private final PrintStream stdOutOrig = System.out; + + /** + * Inject the mocked std-out {@link PrintStream} into the {@link System} class before each test + */ + @Before + public void setUp() { + System.setOut(this.stdOutMock); + } + + /** + * Removed the mocked std-out {@link PrintStream} again from the {@link System} class + */ + @After + public void tearDown() { + System.setOut(this.stdOutOrig); + } + + /** + * Get the mocked stdOut {@link PrintStream} + * + * @return The stdOut print stream mock, renewed before each test + */ + final PrintStream getStdOutMock() { + return this.stdOutMock; + } + +}