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;
+ }
+
+}
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..8e0452fa
--- /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
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..4ff203d4
--- /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;
+ }
+
+}
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
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());
+ }
+
+}
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..dcde88f8
--- /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..007b92a3
--- /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
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;
+ }
+
+}
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
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());
+ }
+ }
+
+}
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..ce54e054
--- /dev/null
+++ b/service-locator/src/test/java/com/iluwatar/servicelocator/ServiceLocatorTest.java
@@ -0,0 +1,46 @@
+package com.iluwatar.servicelocator;
+
+import org.junit.Test;
+
+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
+ *
+ * @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
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);
+ }
+
+}
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));
+ }
+
+}
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..d0359273 100644
--- a/state/src/test/java/com/iluwatar/state/AppTest.java
+++ b/state/src/test/java/com/iluwatar/state/AppTest.java
@@ -3,7 +3,7 @@
import org.junit.Test;
/**
- *
+ *
* Application test
*
*/
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
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
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
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
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
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
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;
+ }
+
+}
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());
+ }
+
+}