Thursday, August 27, 2009

Mockito and the Builder Pattern for speeding up fixtures in Unit Tests

Mockito is a great mocking library on the JVM and I love the terseness of it and all of the functionality that it offers just like EasyMock.

Problem Description

In one of my projects at my current job, I have been using it to mock out classes in my unit tests of some Freemarker templates. Technically, these are more of integration tests, but since the library that it uses to do the generation of the content is well unit-tested itself, I consider this to be in effect unit tests.

So, I came up with using the Builder pattern in conjunction with mockito to simplify the creation of fixtures. We have a complex object that consists of many other objects and in order to test the templates thoroughly, we needed to constructs many different variants of this object. So using the Agile approach I began creating many of these variants by using helper methods. I kept on refactoring until every hierarchical piece was eventually wrapped up in a separate method.

Just as an example of what I am talking about, I will create an imaginary hierarchical structure that mimics my company's object.

Domain

Let's say that the one object that we are talking about is an object that represents a country.

A country is made up of many states.

A state is made up of many cities.

Let's just keep it simple like this for a moment.And we will keep track of the population total at each level and the full name of the leader at that post (president, governor, mayor) and the name of the entitity.

public class Helper { public City getMockedCity(){ City city = mock(City.class); when(city.getName()).thenReturn("New York City"); when(city.getPopulation()).thenReturn(10); when(city.getLeaderFullName()).thenReturn("Michael Bloomberg");

This is quite an easy example, but if you have things that are more complex, you can imagine, this can become quite tedious to maintain as the code/tests change.

Enter the Builder PatternThe idea really came from Groovy's builders and I initially wanted to create the builders in Groovy. I did not have much time to investigate using Groovy's builders, so instead I chose to go with Java since I am much more familiar with it.I created a single Builder per class in the following format:

And I am not going to list the other two Builder implementations of State and City, as they are nearly identical to this implementation.

And now ladies and gentlemen, viola!So now we no longer really need to mess with Mockito's implementation too much when we setup the fixtures, except when the Builders themselves need to be augmented.

We can now build a Country fixture object like so:

Country country = new CountryBuilder() .name("United States") .fullLeaderName("Barrack Obama") .population(1000) .state( new StateBuilder() .name("New York") .fullLeaderName("David Paterson") .population(100) .city( new CityBuilder() .name("New York City") .fullLeaderName("Michael Bloomberg") .population(10) ) // end of city ) // end of state ).build(); // end of country

Now, that is nice and clean!

Maybe next time I will show how to do the same utilizing Groovy's Builder pattern!

Just beware that I did not test this code, but hopefully it will compile. I will try and run it later to make sure it at least compiles. If you find any mistakes, please let me know.

9 comments:

Well in the scenario that I've shown, mock objects are probably not necessary because these are simple POJOs. If you have some really complex logic in the methods (legacy code), then mock objects are a necessity.

Although I love the end result of this (the unit test's setup looks much nicer), it seems really inconvenient and tedious to write these builders yourself. Can you think of a way to automate making these builders?

Followers

Blog Archive

About Me

An application developer and a technologist at heart where I read quite a bit on various subjects in the tech arena. I also like to read for pleasure.
I like snowboarding, doing martial arts, and other random activities.
I like to travel too. That is my passion, but I just don't get to do it often.