Archive for Testing

Unit testing tricks: Look ma, no setters!

Here’s a neat trick if you want set an object in a specific state in a unit test, but you don’t want to violate encapsulation:

    @Test
    public void withdrawShouldReduceBalance() {
        Account account = new Account() {{
            super.balance = 100;
        }};
        account.withdraw(10);
        assertEquals(90, account.getBalance());
    }
 
    @Test(expected=IllegalStateException.class)
    public void overdraftShouldThrow() {
        Account account = new Account() {{
            super.balance = 5;
        }};
        account.withdraw(10);
    }

This seemingly magic code lets me have a protected (but sadly not private) field Account#balance. I can set this field in each individual test method.

It looks very magic, so it deserves a brief explanation:

  1. The first set of curlies create an anonymous subclass of Account. That is: new Account() {}.
  2. The second set of curlies creates an initializer block, that is: a block of code that is added to the constructor.
  3. So in effect: Each test method creates a subclass of Account and modifies the account field in the constructor. This is why Account#balance must be protected instead of private.

This trick (and it is a trick) lets me set up the object under test to any state I want, without needing a special constructor and without breaking encapsulation by adding a setter. However, I’m required to make the fields I want to initialize protected. Additionally, each test method creates one or more new classes. This could potentially affect performance and/or memory use during compilation and/or running of tests. I’ve only used the trick at a small scale, so I don’t know if I’ll run into these issues in the future.

So, what do you think: How big of a “WTF” is this code?

Comments

Five unit testing tips #4: Don’t mock your way into accidental complexity

I’ve all but stopped using mock objects in my tests. The reason is that mocking have had a detrimental effect on the design of my systems. I’ve often ended up having the mocks trick me into adding a needless layer of indirection that does nothing except delegate to the next layer, just to satisfy the mocks.

For a while, I was wondering whether I was the only one with this problem, but then I saw this tutorial on JBehave, which so perfectly illustrates the problem I saw myself doing. Now, I don’t mean to pick on JBehave, or the author of this tutorial. Furthermore, this is not a particularly extreme example of the problem. Rather, the point of this posting is to show that even expert developers run into this trap.

Here is the test from the JBehave tutorial:

@Test
public void shouldProvideNotesToBePlayedInOrder() {
    TabParser parser = mock(TabParser.class);
    String asciiTab = "e|--------A3-B6-";
 
    List<Note> notes = asList(A(3), B(6));
    stub(parser.parse(asciiTab)).toReturn(notes);
 
    Tab tab = new Tab(asciiTab, parser);
 
    List<Note> actualNotes = tab.notesToBePlayed();
 
    ensureThat(notes, equalTo(actualNotes));
}

In other words, the tab’s notes to be played should be equal to the parsed notes.

Here’s the implementation:

public class Tab {
 
    private final List<Note> notes;
 
    public Tab(String asciiTab,
               TabParser parser) {
        notes = parser.parse(asciiTab);
    }
 
    public List<Note> notesToBePlayed() {
        return notes;
    }
}

Whoops! We just introduced a layer in the design that does nothing. As a matter of fact, removing the Tab class from the whole example leaves us with a design that’s easier to understand.

Mocks can be great when you really, really need them. And I’m extremely impressed by the power of mockito. But used inappropriately, mocking can trick you into creating accidental complexity and extra layers of code that does nothing.

Comments

Creative Commons Attribution 3.0 Unported
This work is licensed under a Creative Commons Attribution 3.0 Unported.