In my early unit testing days, if there was a method I wanted to test I would simply expose it and access it in my unit test like this.

public class SingleLinkedListTest {

  @Test
  public void pushFrontOneElement() throws Exception {

      SingleLinkedList<String> list = new SingleLinkedList<String>();
      list.pushFront("a");

      Assert.assertEquals(1, list.size());
      Assert.assertEquals(list.topFront(), "a");
      Assert.assertEquals(list.head(), list.tail());

  }
}

list.head() and list.tail() are internal details of how this LinkedList was built. These shouldn’t be exposed though the public API.

Yet I really want to write some kind of test that forces me to write code like this:

public class SingleLinkedList<T> {
  public void pushFront(T data) {
      Node<T> oldHeader = head;
      head = new Node<T>(data, oldHeader);
      if (size == 0) {
          tail = head;
      }
      size++;
  }
}

What I’ve come to realize over the years is that while writing highly coupled internal unit tests like this isn’t wise, it’s OK if you use it as a temporary step to get you going.

You see early in an APIs life you have a chicken and an egg problem. The public methods you’d ideally like to use to test a method don’t yet exist. But you still some kind of way to test what you are doing. Exposing internals temporarily I think is OK to get you going.

Then you can always come back, and replace the internal method calls with public ones like this.

@Test
public void pushFontTwoElements() throws Exception {

  list.pushFront("a");
  list.pushFront("b");

  Assert.assertEquals(2, list.size());
  Assert.assertEquals(list.topFront(), "b");
  Assert.assertEquals("b", list.popFront());
  Assert.assertEquals("a", list.popFront());
}

So don’t be afraid to test internals if it gets you going. Just don’t forget to come back and replace them once you’ve got your other public APIs in place. This get’s you past the chicken and egg problem. While also eventually leaving you with a nice publicly tested API.

Advertisements