unit testing
Constructor injection, and how it simplifies unit test setup
I’ve recently been reading Growing Object-Oriented Software Guided by Tests (GOOS), and one (of the many) aha moments was a piece of test code that mocked the collaborators and instantiated the object under test – all in the declaration of the test’s private fields. I am particularly fond of this approach for two reasons:
- The test code setup is minimal and easily scanned
- This approach encourages all required collaborators to be passed in through the constructor (aka constructor injection)
I’ve included an illustrative example below using Mockito, the actual test isn’t important but it proves this setup style works.
import org.junit.Test;
public class ItemCheckerTest {
private final ItemFetcher itemFetcher = mock(ItemFetcher.class);
private final Notifier notifier = mock(Notifier.class);
private final ItemChecker itemChecker = new ItemChecker(itemFetcher, notifier);
@Test
public void notifiesStoreManager() throws Exception {
given(itemFetcher.fetch()).willReturn(new FetchedItem());
itemChecker.check();
verify(notifier).notifyStoreManager();
}
...
}
For those unfamiliar with Mockito, the given call stubs a query, while the verify call uses a test spy to check a command call was made.
The important lines are the 3 private member variables of the test class, the first 2 use Mockito’s mock method to instantiate test doubles for our collaborators. The 3rd member variable (itemChecker) is the object under test, you will notice that it is instantiated with both of its required collaborators in the constructor. These 3 lines perform all the wiring we require for our test, without having to resort to @Before methods to set properties.
The reason we can leverage the member variables for this setup is that JUnit creates a new instance of ItemCheckerTest for each of the test methods (@Test). Providing each test with its own set of collaborators ensuring each test runs in isolation.
The most important side effect of setting up the test code in this fashion is that it promotes the use of constructors for wiring up collaborators. Using the constructor for collaborators has a couple of very appealing aspects:
- It becomes impossible to create circular dependencies between your objects
- Your objects are less prone to wiring bugs as they are upfront about their required collaborators.
Why would you want to be upfront about your collaborators, Steve Freeman & Nat Price (GOOS) have this to say:
Partially creating an object and then finishing it off by setting properties is brittle because the programmer has to remember to set all the dependencies. When the object changes to add new dependencies, the existing client code will still compile even though it no longer constructs a valid instance. At best this will cause a NullPointerException, at worst it will fail misleadingly.
Miško Hevery also has a great blog post on constructor vs setter injection.
BDDMockito & Eclipse
On the 23rd of July, Mockito 1.8.0 was released, you can see a full listing of changes in their release notes. One feature that took my fancy was the inclusion of BDD aliases for stubbing an API, instead of using when, the Mockito team now encourage the use of given to bring your tests inline with the BDD style. To illustrate this, here is an example taken from the BDDMockito javadoc.
Seller seller = mock(Seller.class);
Shop shop = new Shop(seller);
public void shouldBuyBread() throws Exception {
//given
given(seller.askForBread()).willReturn(new Bread());
//when
Goods goods = shop.buyBread();
//then
assertThat(goods, containBread());
}
By breaking the test into given, when & then, future maintainers of the tests will more quickly understand which parts of the test relate to setup, exercising the SUT and asserting.
(stealing from Apple’s AppStore ad) What’s great about Eclipse, is that if you want to write a foreach loop, there’s a template for that. If you want to create a unit test, there’s a template for that. Yip there’s an app template for just about anything.
To minimise keystrokes and encourage the use of this style, you can modify the existing Test template as shown below to automatically generate the BDD style comments & statically import the BDDMockito members. To modify the template, navigate to Window > Preferences > Java > Editor > Templates. Click on Test (the JUnit 4 test template) and click edit. Paste in the follow template:
public void ${testname}() throws Exception {
// given ${cursor}
${staticImport:importStatic('org.junit.Assert.*', 'org.mockito.BDDMockito.*')}
// when
// then
}
You are now ready to start writing BDDMockito style unit tests using Eclipse’s template, simply type Test, hit Ctrl+Space and you will be given the following option.

Selecting the option will generate the test method, focus first given to the test name, then to the blank line after // given.

There you have it, a simple Eclipse template to generate your BDDMockito style tests.
Subscribe
Recent Posts
Tags
- "Sorry, no matches found for “tdd” near Auckland, New Zealand" http://t.co/Ahc736MX #auckland #whowantstostartonewithme 2 weeks ago
- Great series on the SOLID design principles for JavaScript http://t.co/ELoPuOH2 2 weeks ago
- Auckland devs, what meetups should I be attending? #java #groovy #ruby #javascript #bdd #tdd 2 weeks ago
- More updates...