diff --git a/TDD-Mocking/pom.xml b/TDD-Mocking/pom.xml new file mode 100644 index 0000000..c4a7072 --- /dev/null +++ b/TDD-Mocking/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + de.edu.hsfulda.ciip.tdd + ConwaysGameOfLife + 1.0-SNAPSHOT + jar + + + 1.8 + 1.8 + + + src/main/java + + + + junit + junit + 4.12 + test + + + org.mockito + mockito-all + 1.10.19 + test + + + diff --git a/TDD-Mocking/src/main/java/de/edu/hsfulda/ciip/tdd/GameCell.java b/TDD-Mocking/src/main/java/de/edu/hsfulda/ciip/tdd/GameCell.java new file mode 100644 index 0000000..ee1de3e --- /dev/null +++ b/TDD-Mocking/src/main/java/de/edu/hsfulda/ciip/tdd/GameCell.java @@ -0,0 +1,37 @@ +package de.edu.hsfulda.ciip.tdd; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collector; +import java.util.stream.Collectors; + +public class GameCell { + + private State state; + private State nextState; + private final List neighbors = new ArrayList<>(); + + public GameCell(State state) { + this.state = state; + } + + public State getState() { + return state; + } + + public void calculateNextGen() { + List neigborStates = neighbors.stream().map(GameCell::getState).collect(Collectors.toList()); + nextState = state.nextBy(neigborStates); + } + + public void activateNextGeneration() { + state = nextState; + } + + public void addNeigbour(GameCell gameCell) { + neighbors.add(gameCell); + } + +} diff --git a/TDD-Mocking/src/main/java/de/edu/hsfulda/ciip/tdd/State.java b/TDD-Mocking/src/main/java/de/edu/hsfulda/ciip/tdd/State.java new file mode 100644 index 0000000..a7589a4 --- /dev/null +++ b/TDD-Mocking/src/main/java/de/edu/hsfulda/ciip/tdd/State.java @@ -0,0 +1,9 @@ +package de.edu.hsfulda.ciip.tdd; + +import java.util.List; + +public interface State { + + State nextBy(List neigborStates); + +} diff --git a/TDD-Mocking/src/main/java/de/edu/hsfulda/ciip/tdd/StateAlive.java b/TDD-Mocking/src/main/java/de/edu/hsfulda/ciip/tdd/StateAlive.java new file mode 100644 index 0000000..28dffe2 --- /dev/null +++ b/TDD-Mocking/src/main/java/de/edu/hsfulda/ciip/tdd/StateAlive.java @@ -0,0 +1,21 @@ +package de.edu.hsfulda.ciip.tdd; + +import java.util.List; + +public class StateAlive implements State { + + @Override + public State nextBy(List neigborStates) { + long alifeNeigbors = countAliveNeighbors(neigborStates); + if(alifeNeigbors >1) { + return this; + } else { + return new StateDead(); + } + } + + private long countAliveNeighbors(List neigborStates) { + return neigborStates.stream().filter(state -> this == state).count(); + } + +} diff --git a/TDD-Mocking/src/main/java/de/edu/hsfulda/ciip/tdd/StateDead.java b/TDD-Mocking/src/main/java/de/edu/hsfulda/ciip/tdd/StateDead.java new file mode 100644 index 0000000..e440494 --- /dev/null +++ b/TDD-Mocking/src/main/java/de/edu/hsfulda/ciip/tdd/StateDead.java @@ -0,0 +1,26 @@ +package de.edu.hsfulda.ciip.tdd; + +import java.util.List; + +public class StateDead implements State { + + private static final int REQUIRED_FOR_CHANGE = 3; + + @Override + public State nextBy(List neigborStates) { + long alifeNeigbors = countAliveNeighbors(neigborStates); + return findNextStateBy(alifeNeigbors); + } + + private State findNextStateBy(long alifeNeigbors) { + if (REQUIRED_FOR_CHANGE == alifeNeigbors) + return this; + else + return this; + } + + private long countAliveNeighbors(List neigborStates) { + return neigborStates.stream().filter(state -> this != state).count(); + } + +} diff --git a/TDD-Mocking/src/test/java/de/edu/hsfulda/ciip/tdd/GameCellTest.java b/TDD-Mocking/src/test/java/de/edu/hsfulda/ciip/tdd/GameCellTest.java new file mode 100644 index 0000000..d81b747 --- /dev/null +++ b/TDD-Mocking/src/test/java/de/edu/hsfulda/ciip/tdd/GameCellTest.java @@ -0,0 +1,77 @@ +package de.edu.hsfulda.ciip.tdd; + +import static org.mockito.Mockito.any; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.*; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import org.hamcrest.CoreMatchers; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +public class GameCellTest { + + @Rule + public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock + State initialState; + + @Mock + State changedState; + + @Test + public void reportsInitiallyProvidesState() { + GameCell cell = new GameCell(initialState); + + State result = cell.getState(); + + assertThat("initial state returned", result, equalTo(initialState)); + } + + @Test + public void changesStateWhenRequested() { + GameCell cell = new GameCell(initialState); + when(initialState.nextBy(any(List.class))).thenReturn(changedState); + + cell.calculateNextGen(); + verify(initialState).nextBy(any(List.class)); + + cell.activateNextGeneration(); + State result = cell.getState(); + assertThat("initial state returned", result, equalTo(changedState)); + } + + @SuppressWarnings("unchecked") + @Test + + public void passesNeigbourStatesForStateChangeCalculation() { + GameCell cell = new GameCell(initialState); + List neighborStates = Arrays.asList(mock(State.class), mock(State.class), mock(State.class), + mock(State.class)); + for (State state : neighborStates) { + cell.addNeigbour(new GameCell(state)); + } + + cell.calculateNextGen(); + ArgumentCaptor passedStates = ArgumentCaptor.forClass(List.class); + verify(initialState).nextBy(passedStates.capture()); + + List statesPassed = passedStates.getValue(); + for (State state : neighborStates) { + assertThat(statesPassed, CoreMatchers.hasItem(state)); + } + } + +} diff --git a/TDD-Mocking/src/test/java/de/edu/hsfulda/ciip/tdd/StatusAliveTest.java b/TDD-Mocking/src/test/java/de/edu/hsfulda/ciip/tdd/StatusAliveTest.java new file mode 100644 index 0000000..6e981a5 --- /dev/null +++ b/TDD-Mocking/src/test/java/de/edu/hsfulda/ciip/tdd/StatusAliveTest.java @@ -0,0 +1,53 @@ +package de.edu.hsfulda.ciip.tdd; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.not; +import static org.junit.Assert.*; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +public class StatusAliveTest { + + @Rule + public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock + State dead; + + @Test + public void changeToDeadIfOneAliveNeighbor() { + // arrange + State stateAlive = new StateAlive(); + List neigborStates = Arrays.asList(stateAlive,dead,dead,dead,dead,dead,dead,dead); + + // act + State result = stateAlive.nextBy(neigborStates); + + // assert + assertNotNull("",result); + assertThat("changed to dead", result.getClass(), not(equalTo(stateAlive.getClass()))); + } + + @Test + public void KeepSateAliveWithTwoLivingNeighbors() { + // arrange + State stateAlive = new StateAlive(); + List neigborStates = Arrays.asList(stateAlive,stateAlive,dead,dead,dead,dead,dead,dead); + + // act + State result = stateAlive.nextBy(neigborStates); + + // assert + assertNotNull("",result); + assertThat("Still alive", result.getClass(), (equalTo(stateAlive.getClass()))); + } + + +} diff --git a/TDD-Mocking/src/test/java/de/edu/hsfulda/ciip/tdd/StatusDeadTest.java b/TDD-Mocking/src/test/java/de/edu/hsfulda/ciip/tdd/StatusDeadTest.java new file mode 100644 index 0000000..bfb6a3b --- /dev/null +++ b/TDD-Mocking/src/test/java/de/edu/hsfulda/ciip/tdd/StatusDeadTest.java @@ -0,0 +1,61 @@ +package de.edu.hsfulda.ciip.tdd; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.mock; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class StatusDeadTest { + private static State[] states = { mock(State.class, "alife"), new StateDead() }; + private static final int alife = 0; + private static final int dead = 1; + + @Parameters(name = "{index}: condition: {0} expected: {2}") + public static Collection data() { + + return Arrays + .asList(new Object[][] { { "all dead", 0, dead }, { "one alife", 1, dead }, { "two alife", 2, dead }, + { "four alife", 4, dead }, { "five alife", 5, dead }, { "three alife", 3, alife } }); + } + + @Parameter // first data value (0) is default + public /* NOT private */ String assertMessage; + + @Parameter(1) + public /* NOT private */ int aliveneigborCount; + + @Parameter(2) + public /* NOT private */ int expected; + + @Test + public void calculateNextState() { + // arrange + List neigborStates = new ArrayList<>(); + for (int i = 0; i < aliveneigborCount; i++) + neigborStates.add(states[alife]); + while (neigborStates.size() < 8) { + neigborStates.add(states[dead]); + } + Collections.shuffle(neigborStates); + + // act + State stateDead = states[dead]; + State result = stateDead.nextBy(neigborStates); + + // assert + assertThat(assertMessage, result, equalTo(states[expected])); + } + +}