NodeItemTest: overhaul of test suite

This commit is contained in:
Paul Campbell 2016-05-24 11:53:52 +01:00
parent b456e18316
commit 180f325f79

View file

@ -1,13 +1,15 @@
package net.kemitix.node; package net.kemitix.node;
import lombok.val; import lombok.val;
import org.junit.Assert; import org.assertj.core.api.SoftAssertions;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.hamcrest.CoreMatchers.hasItem; import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Optional; import java.util.Optional;
@ -19,32 +21,51 @@ import java.util.Optional;
*/ */
public class NodeItemTest { public class NodeItemTest {
/** @Rule
* Class under test. public ExpectedException exception = ExpectedException.none();
*/
private Node<String> node; private Node<String> node;
/**
* Test that node data is recoverable.
*/
@Test @Test
public void shouldReturnNodeData() { public void getDataReturnsData() {
//given //given
val data = "this node data"; val data = "this node data";
//when //when
node = new NodeItem<>(data); node = new NodeItem<>(data);
//then //then
Assert.assertThat("can get the data from a node", node.getData(), assertThat(node.getData()).as("can get the data from a node").
is(data)); isSameAs(data);
} }
/** @Test
* Test that passing null as node data throws exception. public void canCreateAnEmptyAndUnnamedNode() {
*/
@Test(expected = NullPointerException.class)
public void shouldThrowNPEWhenDataIsNull() {
//when //when
node = new NodeItem<>(null); node = new NodeItem<>(null);
//then
SoftAssertions softly = new SoftAssertions();
softly.assertThat(node.isEmpty()).as("node is empty").isTrue();
softly.assertThat(node.isNamed()).as("node is unnamed").isFalse();
softly.assertAll();
}
@Test
public void canCreateNodeWithParentAndCustomNameSupplier() {
//given
node = new NodeItem<>(null, n -> "root name supplier");
//when
val child = new NodeItem<>(null, n -> "overridden", node);
//then
assertThat(child.getName()).isEqualTo("overridden");
}
@Test
public void canSetName() {
//given
node = new NodeItem<>(null);
//when
node.setName("named");
//then
assertThat(node.getName()).isEqualTo("named");
} }
/** /**
@ -53,10 +74,10 @@ public class NodeItemTest {
@Test @Test
public void shouldHaveNullForDefaultParent() { public void shouldHaveNullForDefaultParent() {
//given //given
node = new NodeItem<>("data"); node = new NodeItem<>("data", Node::getData);
//then //then
Assert.assertThat("node created without a parent has null as parent", assertThat(node.getParent()).as(
node.getParent(), nullValue()); "node created without a parent has null as parent").isNull();
} }
/** /**
@ -65,23 +86,26 @@ public class NodeItemTest {
@Test @Test
public void shouldReturnNodeParent() { public void shouldReturnNodeParent() {
//given //given
val parent = new NodeItem<String>("parent"); val parent = new NodeItem<String>("parent", Node::getData);
//when //when
node = new NodeItem<>("subject", parent); node = new NodeItem<>("subject", parent);
//then //then
Assert.assertThat("node created with a parent can return the parent", assertThat(node.getParent()).as(
node.getParent(), is(parent)); "node created with a parent can return the parent")
.isSameAs(parent);
} }
/** /**
* Test that setting the parent on a node where the proposed parent is a * Test that setting the parent on a node where the proposed parent is a
* child of the node throws an exception. * child of the node throws an exception.
*/ */
@Test(expected = NodeException.class) @Test
public void shouldThrowNEWhenSettingParentToAChild() { public void setParentShouldThrowNodeExceptionWhenParentIsAChild() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
val child = new NodeItem<String>("child", node); val child = new NodeItem<String>("child", node);
exception.expect(NodeException.class);
exception.expectMessage("Parent is a descendant");
//when //when
node.setParent(child); node.setParent(child);
} }
@ -91,16 +115,16 @@ public class NodeItemTest {
* child of the parent. * child of the parent.
*/ */
@Test @Test
@SuppressWarnings("unchecked")
public void shouldAddNewNodeAsChildToParent() { public void shouldAddNewNodeAsChildToParent() {
//given //given
val parent = new NodeItem<String>("parent"); val parent = new NodeItem<String>("parent", Node::getData);
//when //when
node = new NodeItem<>("subject", parent); node = new NodeItem<>("subject", parent);
//then //then
Assert.assertThat( assertThat(parent.getChildren()).as(
"when a node is created with a parent, the parent has the new" "when a node is created with a parent, the parent has the new"
+ " node among it's children", parent.getChildren(), + " node among it's children").contains(node);
hasItem(node));
} }
/** /**
@ -109,23 +133,25 @@ public class NodeItemTest {
@Test @Test
public void shouldReturnSetParent() { public void shouldReturnSetParent() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
val parent = new NodeItem<String>("parent"); val parent = new NodeItem<String>("parent", Node::getData);
//when //when
node.setParent(parent); node.setParent(parent);
//then //then
Assert.assertThat( assertThat(node.getParent()).as(
"when a node is assigned a new parent that parent can be " "when a node is assigned a new parent that parent can be "
+ "returned", node.getParent(), is(parent)); + "returned").isSameAs(parent);
} }
/** /**
* Test that we throw an exception when passed null. * Test that we throw an exception when passed null.
*/ */
@Test(expected = NullPointerException.class) @Test
public void shouldThrowNPEWhenSetParentNull() { public void shouldThrowNPEWhenSetParentNull() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
exception.expect(NullPointerException.class);
exception.expectMessage("parent");
//when //when
node.setParent(null); node.setParent(null);
} }
@ -134,10 +160,12 @@ public class NodeItemTest {
* Test that we throw an exceptions when attempting to node as its own * Test that we throw an exceptions when attempting to node as its own
* parent. * parent.
*/ */
@Test(expected = NodeException.class) @Test
public void shouldThrowNEWhenSetParentSelf() { public void setParentShouldThrowNodeExceptionWhenParentIsSelf() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
exception.expect(NodeException.class);
exception.expectMessage("Parent is a descendant");
//when //when
node.setParent(node); node.setParent(node);
} }
@ -149,19 +177,18 @@ public class NodeItemTest {
@Test @Test
public void shouldUpdateOldParentWhenNodeSetToNewParent() { public void shouldUpdateOldParentWhenNodeSetToNewParent() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
val child = node.createChild("child"); val child = node.createChild("child");
val newParent = new NodeItem<String>("newParent"); val newParent = new NodeItem<String>("newParent", Node::getData);
//when //when
child.setParent(newParent); child.setParent(newParent);
//then //then
Assert.assertThat( assertThat(child.getParent()).as(
"when a node is assigned a new parent, the old parent is " "when a node is assigned a new parent, the old parent is "
+ "replaced", child.getParent(), is(newParent)); + "replaced").isSameAs(newParent);
Assert.assertThat( assertThat(node.getChild("child").isPresent()).as(
"when a node is assigned a new parent, the old parent no " "when a node is assigned a new parent, the old parent no "
+ "longer has the node among it's children", + "longer has the node among it's children").isFalse();
node.getChild("child").isPresent(), is(false));
} }
/** /**
@ -171,30 +198,31 @@ public class NodeItemTest {
@Test @Test
public void shouldRemoveNodeFromOldParentWhenAddedAsChildToNewParent() { public void shouldRemoveNodeFromOldParentWhenAddedAsChildToNewParent() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
val child = node.createChild("child"); val child = node.createChild("child");
val newParent = new NodeItem<String>("newParent"); val newParent = new NodeItem<String>("newParent", Node::getData);
//when //when
newParent.addChild(child); newParent.addChild(child);
//then //then
Assert.assertThat( assertThat(child.getParent()).as(
"when a node with an existing parent is added as a child " "when a node with an existing parent is added as a child "
+ "to another node, then the old parent is replaced", + "to another node, then the old parent is replaced")
child.getParent(), is(newParent)); .isSameAs(newParent);
Assert.assertThat( assertThat(node.getChild("child").isPresent()).as(
"when a node with an existing parent is added as a child to " "when a node with an existing parent is added as a child to "
+ "another node, then the old parent no longer has " + "another node, then the old parent no longer has "
+ "the node among it's children", + "the node among it's children").isFalse();
node.getChild("child").isPresent(), is(false));
} }
/** /**
* Test that adding null as a child throws an exception. * Test that adding null as a child throws an exception.
*/ */
@Test(expected = NullPointerException.class) @Test
public void shouldThrowNPEWhenAddingNullAsChild() { public void shouldThrowNPEWhenAddingNullAsChild() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
exception.expect(NullPointerException.class);
exception.expectMessage("child");
//when //when
node.addChild(null); node.addChild(null);
} }
@ -203,25 +231,28 @@ public class NodeItemTest {
* Test that adding a child is returned. * Test that adding a child is returned.
*/ */
@Test @Test
@SuppressWarnings("unchecked")
public void shouldReturnAddedChild() { public void shouldReturnAddedChild() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
val child = new NodeItem<String>("child"); val child = new NodeItem<String>("child", Node::getData);
//when //when
node.addChild(child); node.addChild(child);
//then //then
Assert.assertThat( assertThat(node.getChildren()).as(
"when a node is added as a child, the node is among the " "when a node is added as a child, the node is among the "
+ "children", node.getChildren(), hasItem(child)); + "children").contains(child);
} }
/** /**
* Test that adding a node as it's own child throws an exception. * Test that adding a node as it's own child throws an exception.
*/ */
@Test(expected = NodeException.class) @Test
public void shouldThrowNEWhenAddingANodeAsOwnChild() { public void addChildShouldThrowNodeExceptionWhenAddingANodeAsOwnChild() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
exception.expect(NodeException.class);
exception.expectMessage("Child is an ancestor");
//then //then
node.addChild(node); node.addChild(node);
} }
@ -229,10 +260,12 @@ public class NodeItemTest {
/** /**
* Test that adding a node to itself as a child causes an exception. * Test that adding a node to itself as a child causes an exception.
*/ */
@Test(expected = NodeException.class) @Test
public void shouldThrowWhenAddingSelfAsChild() { public void addChildShouldThrowNodeExceptionWhenAddingSelfAsChild() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
exception.expect(NodeException.class);
exception.expectMessage("Child is an ancestor");
//when //when
node.addChild(node); node.addChild(node);
} }
@ -241,11 +274,13 @@ public class NodeItemTest {
* Test that adding the parent of a node to the node as a child causes an * Test that adding the parent of a node to the node as a child causes an
* exception. * exception.
*/ */
@Test(expected = NodeException.class) @Test
public void shouldThrowWhenAddingParentAsChild() { public void addChildShouldThrowNodeExceptionWhenChildIsParent() {
//given //given
val parent = new NodeItem<String>("parent"); val parent = new NodeItem<String>("parent", Node::getData);
node = new NodeItem<>("subject", parent); node = new NodeItem<>("subject", parent);
exception.expect(NodeException.class);
exception.expectMessage("Child is an ancestor");
//when //when
node.addChild(parent); node.addChild(parent);
} }
@ -254,12 +289,14 @@ public class NodeItemTest {
* Test that adding the grandparent to a node as a child causes an * Test that adding the grandparent to a node as a child causes an
* exception. * exception.
*/ */
@Test(expected = NodeException.class) @Test
public void shouldThrowWhenAddingGrandParentAsChild() { public void addChildShouldThrowNodeExceptionWhenAddingGrandParentAsChild() {
//given //given
val grandParent = new NodeItem<String>("grandparent"); val grandParent = new NodeItem<String>("grandparent", Node::getData);
val parent = new NodeItem<String>("parent", grandParent); val parent = new NodeItem<String>("parent", grandParent);
node = new NodeItem<>("subject", parent); node = new NodeItem<>("subject", parent);
exception.expect(NodeException.class);
exception.expectMessage("Child is an ancestor");
//when //when
node.addChild(grandParent); node.addChild(grandParent);
} }
@ -270,14 +307,14 @@ public class NodeItemTest {
@Test @Test
public void shouldSetParentOnChildWhenAddedAsChild() { public void shouldSetParentOnChildWhenAddedAsChild() {
//given //given
val child = new NodeItem<String>("child"); val child = new NodeItem<String>("child", Node::getData);
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
//when //when
node.addChild(child); node.addChild(child);
//then //then
Assert.assertThat( assertThat(child.getParent()).as(
"when a node is added as a child, the child has the node as " "when a node is added as a child, the child has the node as "
+ "its parent", child.getParent(), is(node)); + "its parent").isSameAs(node);
} }
/** /**
@ -287,7 +324,7 @@ public class NodeItemTest {
public void shouldWalkTreeToNode() { public void shouldWalkTreeToNode() {
//given //given
val grandparent = "grandparent"; val grandparent = "grandparent";
val grandParentNode = new NodeItem<String>(grandparent); val grandParentNode = new NodeItem<String>(grandparent, Node::getData);
val parent = "parent"; val parent = "parent";
val parentNode = new NodeItem<String>(parent, grandParentNode); val parentNode = new NodeItem<String>(parent, grandParentNode);
val subject = "subject"; val subject = "subject";
@ -295,12 +332,12 @@ public class NodeItemTest {
//when //when
val result = grandParentNode.walkTree(Arrays.asList(parent, subject)); val result = grandParentNode.walkTree(Arrays.asList(parent, subject));
//then //then
Assert.assertThat("when we walk the tree to a node it is found", assertThat(result.isPresent()).as(
result.isPresent(), is(true)); "when we walk the tree to a node it is found").isTrue();
if (result.isPresent()) { if (result.isPresent()) {
Assert.assertThat( assertThat(result.get()).as(
"when we walk the tree to a node the correct node is found", "when we walk the tree to a node the correct node is found")
result.get(), is(node)); .isSameAs(node);
} }
} }
@ -312,24 +349,26 @@ public class NodeItemTest {
public void shouldNotFindNonExistentChildNode() { public void shouldNotFindNonExistentChildNode() {
//given //given
val parent = "parent"; val parent = "parent";
val parentNode = new NodeItem<String>(parent); val parentNode = new NodeItem<String>(parent, Node::getData);
val subject = "subject"; val subject = "subject";
node = new NodeItem<>(subject, parentNode); node = new NodeItem<>(subject, parentNode);
//when //when
val result = parentNode.walkTree(Arrays.asList(subject, "no child")); val result = parentNode.walkTree(Arrays.asList(subject, "no child"));
//then //then
Assert.assertThat( assertThat(result.isPresent()).as(
"when we walk the tree to a node that doesn't exists, nothing" "when we walk the tree to a node that doesn't exists, nothing"
+ " is found", result.isPresent(), is(false)); + " is found").isFalse();
} }
/** /**
* Test that when we pass null we get an exception. * Test that when we pass null we get an exception.
*/ */
@Test(expected = NullPointerException.class) @Test
public void shouldThrowNEWhenWalkTreeNull() { public void shouldThrowNEWhenWalkTreeNull() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
exception.expect(NullPointerException.class);
exception.expectMessage("path");
//when //when
node.walkTree(null); node.walkTree(null);
} }
@ -341,9 +380,11 @@ public class NodeItemTest {
@Test @Test
public void shouldReturnEmptyForEmptyWalkTreePath() { public void shouldReturnEmptyForEmptyWalkTreePath() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
//when //when
node.walkTree(Collections.emptyList()); val result = node.walkTree(Collections.emptyList());
//then
assertThat(result).isEmpty();
} }
/** /**
@ -352,7 +393,7 @@ public class NodeItemTest {
@Test @Test
public void shouldCreateDescendantNodes() { public void shouldCreateDescendantNodes() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
val alphaData = "alpha"; val alphaData = "alpha";
val betaData = "beta"; val betaData = "beta";
val gammaData = "gamma"; val gammaData = "gamma";
@ -361,36 +402,34 @@ public class NodeItemTest {
Arrays.asList(alphaData, betaData, gammaData)); Arrays.asList(alphaData, betaData, gammaData));
//then //then
val alphaOptional = node.getChild(alphaData); val alphaOptional = node.getChild(alphaData);
Assert.assertThat( assertThat(alphaOptional.isPresent()).as(
"when creating a descendant line, the first element is found", "when creating a descendant line, the first element is found")
alphaOptional.isPresent(), is(true)); .isTrue();
if (alphaOptional.isPresent()) { if (alphaOptional.isPresent()) {
val alpha = alphaOptional.get(); val alpha = alphaOptional.get();
Assert.assertThat( assertThat(alpha.getParent()).as(
"when creating a descendant line, the first element has " "when creating a descendant line, the first element has "
+ "the current node as its parent", + "the current node as its parent").isSameAs(node);
alpha.getParent(), is(node));
val betaOptional = alpha.getChild(betaData); val betaOptional = alpha.getChild(betaData);
Assert.assertThat( assertThat(betaOptional.isPresent()).as(
"when creating a descendant line, the second element is " "when creating a descendant line, the second element is "
+ "found", betaOptional.isPresent(), is(true)); + "found").isTrue();
if (betaOptional.isPresent()) { if (betaOptional.isPresent()) {
val beta = betaOptional.get(); val beta = betaOptional.get();
Assert.assertThat( assertThat(beta.getParent()).as(
"when creating a descendant line, the second element " "when creating a descendant line, the second element "
+ "has the first as its parent", + "has the first as its parent")
beta.getParent(), is(alpha)); .isSameAs(alpha);
val gammaOptional = beta.getChild(gammaData); val gammaOptional = beta.getChild(gammaData);
Assert.assertThat( assertThat(gammaOptional.isPresent()).as(
"when creating a descendant line, the third element " "when creating a descendant line, the third element "
+ "is found", gammaOptional.isPresent(), + "is found").isTrue();
is(true));
if (gammaOptional.isPresent()) { if (gammaOptional.isPresent()) {
val gamma = gammaOptional.get(); val gamma = gammaOptional.get();
Assert.assertThat( assertThat(gamma.getParent()).as(
"when creating a descendant line, the third " "when creating a descendant line, the third "
+ "element has the second as its parent", + "element has the second as its parent")
gamma.getParent(), is(beta)); .isSameAs(beta);
} }
} }
} }
@ -400,10 +439,12 @@ public class NodeItemTest {
* Test that if we pass null to create a chain of descendant nodes we get an * Test that if we pass null to create a chain of descendant nodes we get an
* exception. * exception.
*/ */
@Test(expected = NullPointerException.class) @Test
public void shouldThrowNPEWhenCreateDescendantNull() { public void createDescendantLineShouldThrowNPEWhenDescendantsAreNull() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
exception.expect(NullPointerException.class);
exception.expectMessage("descendants");
//when //when
node.createDescendantLine(null); node.createDescendantLine(null);
} }
@ -414,13 +455,13 @@ public class NodeItemTest {
@Test @Test
public void shouldChangeNothingWhenCreateDescendantEmpty() { public void shouldChangeNothingWhenCreateDescendantEmpty() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
//when //when
node.createDescendantLine(Collections.emptyList()); node.createDescendantLine(Collections.emptyList());
//then //then
Assert.assertThat( assertThat(node.getChildren()).as(
"when creating a descendant line from an empty list, nothing " "when creating a descendant line from an empty list, nothing "
+ "is created", node.getChildren().size(), is(0)); + "is created").isEmpty();
} }
/** /**
@ -429,15 +470,15 @@ public class NodeItemTest {
@Test @Test
public void shouldFindExistingChildNode() { public void shouldFindExistingChildNode() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
val childData = "child"; val childData = "child";
val child = new NodeItem<String>(childData, node); val child = new NodeItem<String>(childData, node);
//when //when
val found = node.findOrCreateChild(childData); val found = node.findOrCreateChild(childData);
//then //then
Assert.assertThat( assertThat(found).as(
"when searching for a child by data, the matching child is " "when searching for a child by data, the matching child is "
+ "found", found, is(child)); + "found").isSameAs(child);
} }
/** /**
@ -446,23 +487,25 @@ public class NodeItemTest {
@Test @Test
public void shouldFindCreateNewChildNode() { public void shouldFindCreateNewChildNode() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
val childData = "child"; val childData = "child";
//when //when
val found = node.findOrCreateChild(childData); val found = node.findOrCreateChild(childData);
//then //then
Assert.assertThat( assertThat(found.getData()).as(
"when searching for a child by data, a new node is created", "when searching for a child by data, a new node is created")
found.getData(), is(childData)); .isSameAs(childData);
} }
/** /**
* Test that if we pass null we get an exception. * Test that if we pass null we get an exception.
*/ */
@Test(expected = NullPointerException.class) @Test
public void shouldThrowNPEFWhenFindOrCreateChildNull() { public void findOrCreateChildShouldThrowNPEFWhenChildIsNull() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
exception.expect(NullPointerException.class);
exception.expectMessage("child");
//when //when
node.findOrCreateChild(null); node.findOrCreateChild(null);
} }
@ -473,29 +516,31 @@ public class NodeItemTest {
@Test @Test
public void shouldGetChild() { public void shouldGetChild() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
val childData = "child"; val childData = "child";
val child = new NodeItem<String>(childData); val child = new NodeItem<String>(childData, Node::getData);
node.addChild(child); node.addChild(child);
//when //when
val found = node.getChild(childData); val found = node.getChild(childData);
//then //then
Assert.assertThat("when retrieving a child by its data, it is found", assertThat(found.isPresent()).as(
found.isPresent(), is(true)); "when retrieving a child by its data, it is found").isTrue();
if (found.isPresent()) { if (found.isPresent()) {
Assert.assertThat( assertThat(found.get()).as(
"when retrieving a child by its data, it is the expected " "when retrieving a child by its data, it is the expected "
+ "node", found.get(), is(child)); + "node").isSameAs(child);
} }
} }
/** /**
* Test that we throw an exception when passed null. * Test that we throw an exception when passed null.
*/ */
@Test(expected = NullPointerException.class) @Test
public void shouldThrowNPEWhenGetChildNull() { public void getChildShouldThrowNPEWhenThereIsNoChild() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("data", Node::getData);
exception.expect(NullPointerException.class);
exception.expectMessage("child");
//when //when
node.getChild(null); node.getChild(null);
} }
@ -507,34 +552,196 @@ public class NodeItemTest {
@Test @Test
public void shouldCreateChild() { public void shouldCreateChild() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
val childData = "child"; val childData = "child";
//when //when
val child = node.createChild(childData); val child = node.createChild(childData);
//then //then
Assert.assertThat( assertThat(child.getParent()).as(
"when creating a child node, the child has the current node " "when creating a child node, the child has the current node "
+ "as its parent", child.getParent(), is(node)); + "as its parent").isSameAs(node);
val foundChild = node.getChild(childData); val foundChild = node.getChild(childData);
Assert.assertThat( assertThat(foundChild.isPresent()).as(
"when creating a child node, the child can be found by its " "when creating a child node, the child can be found by its "
+ "data", foundChild.isPresent(), is(true)); + "data").isTrue();
if (foundChild.isPresent()) { if (foundChild.isPresent()) {
Assert.assertThat( assertThat(foundChild.get()).as(
"when creating a child node, the correct child can be " "when creating a child node, the correct child can be "
+ "found by its data", foundChild.get(), is(child)); + "found by its data").isSameAs(child);
} }
} }
/** /**
* Test that we throw an exception when passed null. * Test that we throw an exception when passed null.
*/ */
@Test(expected = NullPointerException.class) @Test
public void shouldThrowNPEWhenCreateChildNull() { public void createChildShouldThrowNPEWhenChildIsNull() {
//given //given
node = new NodeItem<>("subject"); node = new NodeItem<>("subject", Node::getData);
exception.expect(NullPointerException.class);
exception.expectMessage("child");
//when //when
node.createChild(null); node.createChild(null);
} }
@Test
public void getNameShouldBeCorrect() {
//given
node = new NodeItem<>("subject", Node::getData);
//then
assertThat(node.getName()).isEqualTo("subject");
}
@Test
public void getNameShouldUseParentNameSupplier() {
//given
val root = new NodeItem<String>("root", Node::getData);
node = new NodeItem<>("child", root);
//then
assertThat(node.getName()).isEqualTo("child");
}
@Test
public void getNameShouldReturnNameForNonStringData() {
val root = new NodeItem<LocalDate>(LocalDate.parse("2016-05-23"),
n -> n.getData().format(DateTimeFormatter.BASIC_ISO_DATE));
//then
assertThat(root.getName()).isEqualTo("20160523");
}
@Test
public void getNameShouldUseClosestNameSupplier() {
node = new NodeItem<>("root", Node::getData);
val child = new NodeItem<String>("child", Object::toString);
node.addChild(child);
val grandChild = new NodeItem<>("grandchild", child);
//then
assertThat(node.getName()).isEqualTo("root");
assertThat(child.getName()).isNotEqualTo("child");
assertThat(grandChild.getName()).isNotEqualTo("grandchild");
}
@Test
public void getNameShouldWorkWithoutNameSupplier() {
node = new NodeItem<>(null, "root");
val namedchild = new NodeItem<>("named", "Alice", node);
//then
assertThat(node.getName()).isEqualTo("root");
assertThat(namedchild.getName()).isEqualTo("Alice");
}
@Test
public void canCreateRootNodeWithoutData() {
node = new NodeItem<>(null, "empty");
assertThat(node.getData()).isNull();
}
@Test
public void canCreateRootNodeWithoutDataButWithNameSupplier() {
node = new NodeItem<>(null, Node::getData);
assertThat(node.getData()).isNull();
}
@Test
public void getChildNamedFindsChild() {
//given
node = new NodeItem<>(null, "root");
val alpha = new NodeItem<String>(null, "alpha");
val beta = new NodeItem<String>(null, "beta");
node.addChild(alpha);
node.addChild(beta);
//when
val result = node.getChildNamed("alpha");
//then
assertThat(result).isSameAs(alpha);
}
@Test
public void getChildNamedFindsNothing() {
//given
node = new NodeItem<>(null, "root");
val alpha = new NodeItem<String>(null, "alpha");
val beta = new NodeItem<String>(null, "beta");
node.addChild(alpha);
node.addChild(beta);
exception.expect(NodeException.class);
exception.expectMessage("Named child not found");
//when
node.getChildNamed("gamma");
}
@Test
public void nodeNamesAreUniqueWithinAParent() {
//given
node = new NodeItem<>(null, "root");
val alpha = new NodeItem<String>(null, "alpha");
node.addChild(alpha);
val beta = new NodeItem<String>(null, "alpha");
exception.expect(NodeException.class);
exception.expectMessage("Node with that name already exists here");
//when
node.addChild(beta);
}
@Test
public void canPlaceNodeInTreeByPathNames() {
//given
node = new NodeItem<>(null, "root"); // create a root
val four = new NodeItem<String>("data", "four");
//when
node.placeNodeIn(four, "one", "two", "three");
//then
val three = four.getParent();
assertThat(four.getParent()).as("add node to a tree").isNotNull();
assertThat(three.getName()).isEqualTo("three");
val two = three.getParent();
assertThat(two.getName()).isEqualTo("two");
val one = two.getParent();
assertThat(one.getName()).isEqualTo("one");
assertThat(one.getParent()).isSameAs(node);
assertThat(node.getChildNamed("one")
.getChildNamed("two")
.getChildNamed("three")
.getChildNamed("four")).isSameAs(four);
}
@Test
@SuppressWarnings("unchecked")
public void canPlaceInTreeUnderExistingNode() {
//given
node = new NodeItem<>(null, "root");
val child = new NodeItem<String>("child data", "child");
val grandchild = new NodeItem<String>("grandchild data", "grandchild");
//when
node.placeNodeIn(child); // as root/child
node.placeNodeIn(grandchild, "child"); // as root/child/grandchild
//then
assertThat(node.getChildNamed("child")).as("child").isSameAs(child);
assertThat(node.getChildNamed("child").getChildNamed("grandchild")).as(
"grandchild").isSameAs(grandchild);
}
@Test
@SuppressWarnings("unchecked")
public void canPlaceInTreeAboveExistingNode() {
//given
node = new NodeItem<>(null, "root");
val child = new NodeItem<String>("child data", "child");
val grandchild = new NodeItem<String>("grandchild data", "grandchild");
//when
node.placeNodeIn(grandchild, "child");
node.placeNodeIn(child);
//then
assertThat(node.getChildNamed("child")).as("child").isSameAs(child);
assertThat(node.getChildNamed("child").getChildNamed("grandchild")).as(
"grandchild").isSameAs(grandchild);
}
@Test
public void removingParentFromNodeWithNoParentIsNoop() {
//given
node = new NodeItem<>(null);
//when
node.removeParent();
}
} }