Mockito: drink it without moderation

Mockito is probably my favorite java library. It is a popular mocking tool, mostly used to isolate a piece of code during unit-testing.

Let’s go through its main benefits with a simple example. If you already know Mockito you can skip this first section.

1. Mockito in action

Imagine the following requirement: publish a blog post and announce it on twitter with a shortened URL.

We’ll start with some design and decide that the following method will fulfill the requirement:

public class BlogService {
    /**
     * Publish a blog post and announce it on twitter.
     */
    public void publishPost(int postId) {
    }
}

Listing 1 – Designing the interface

Then, we’ll do some TDD and write a test case before coding the implementation. To make it simple, we’ll assume the necessary data is already loaded into the DB with id 1. There are a few options for this to work.

    public void testPublishPost() {
        blogService.publishPost(1);
        post = blogService.getPost(1);
        assertTrue(post.isPublished()); // JUnit assertion
    }

Listing 2 – Writing a test case

Here you notice that we need a database connectivity, that’s totally fine and recommended for unit-testing, unless you suffer of paramockia which is a special form of obsessive–compulsive disorder.

Now let’s implement our method to make this test pass:

    /**
     * Publish a blog post and announce it on twitter.
     */
    public void publishPost(int postId) {
        Post post = blogDao.getPostById(postId);
        post.setPublished(true);
        blogDao.savePost(post);

        String shortUrl = urlShortenerService.shortenUrl(post.getUrl());

        String tweet = "New blog post: " + shortUrl.trim(); // contrived but it will help
        twitterService.post(tweet);
   }

Listing 3 – Implementing

Let’s consider that urlShortenerService and twitterService connect to external systems (bit.ly and twitter.com), that would be annoying to really call these systems during unit-testing. That’s where Mockito will save the day.

We will revisit our test case to mock those 2 services:

    public void testPublishPost() {
        UrlShortener mockShortener = mock(UrlShortener.class);
        blogService.setUrlShortener(mockShortener);

        TwitterService mockTwitter = mock(TwitterService.class);
        blogService.setTwitterService(mockTwitter);

        blogService.publishPost(1);
        post = blogService.getPost(1);
        assertTrue(post.getPublish()); // JUnit assertion
    }

Listing 4 – Mocking

Now we can run our test and … BOOM ! NullPointerException in BlogService (line 11 of Listing 3, I told you trimming would help). By default, Mockito will create a mock object which implements all the non-private methods of the class to mock. But all the methods whose return type is not void, will return null. So we’re trying to trim null.

Let’s revisit our test case and tell Mockito to return something. We’ll also use the verify method to check that the twitterService is called with the argument we expect.

    public void testPublishPost() {
        UrlShortener mockShortener = mock(UrlShortener.class);
        when(mockShortener.shortenUrl(anyString())).thenReturn("short");
        blogService.setUrlShortener(mockShortener);

        TwitterService mockTwitter = mock(TwitterService.class);
        blogService.setTwitterService(mockTwitter);

        blogService.publishPost(1);
        post = blogService.getPost(1);
        assertTrue(post.getPublish()); // JUnit assertion

        verify(mockTwitter).post("New blog post: short");
    }

Listing 5 – Fixing and verifying

Et voila, our test case is now successful. Our business logic has been isolated and unit-tested.

One last note about using Spring to inject mocks, that’s just a no-brainer:

	<bean id="twitterService" class="org.mockito.Mockito" factory-method="mock">
		<constructor-arg value="com.domain.TwitterService" />
	</bean>

Listing 6 – Mocked spring bean

This, with just a few other well documented features, will take you a long way when it comes to mocking and unit-testing.

2. What is so cool about Mockito?

Szczepan Faber, the author of Mockito, has a few things to say on why his tool is well done and conceptually right for unit-testing. I will just focus on a few details which struck me.

Great name

What a great branding! And there’s a great dose of humor on Mockito home page. I love it. Maybe that shouldn’t matter but we, programmers (should I say human beings …), are just kids. We love playing with new toys as long as they’re attractive and fun.

Simplicity: no boilerplate code to write

Mockito is outrageously simple. In fact, I wish I could write something so simple. All the complexity is hidden from the end-user, providing only a simple, yet powerful, API.

This API consists mostly of static methods, that’s an awesome design decision in this case. No need to instantiate unnecessary objects for the single purpose to look object oriented.

Let’s compare this to, let’s say, log4j, which is also a simple and popular library.

private static Logger logger = Logger.getLogger(MyClass.class);

Couldn’t we avoid instantiating these loggers in every class? 99% of the time by putting the current class as constructor argument, which is error-prone.

Generics at their best

Outside of the JDK, Mockito is the smartest usage of generics I’ve ever seen, even including the JDK maybe.

Let’s consider 3 of the main methods we covered in the first section, mock, when and verify. They all use a type parameter, which allows them to return an object of the type needed by the end-user.

For the method mock, it’s obvious, Mockito uses the magic of cglib to create a mock of the specified type, the class to mock.

The method when is not less magical. Here is again the syntax I used earlier:

when(mockShortener.shortenUrl(anyString())).thenReturn("short");

Think about it twice. How would you implement that yourself? Not easy, right?

Our real shortenUrl method was returning a String. The mocked version has to return an object which is a String so it can be used in the code to test. But it also has to be more than a String, so that when used as argument to the when method, it provides a way to modify the behavior of the mock.

The thenReturn method uses a type parameter to ensure the developer pass an object of the same type than the return type of the method “passed” to when  … Simple in the API, impressive under the hood.

The verify method is of the same caliber.

verify(mockTwitter).post("New blog post: short");

It returns an object implementing all the methods of the mocked class, allowing another nice method chaining. But when a method of this object is called, it checks the state of the mock against the given argument to validate it was actually called this way in our tested code.

3. Conclusion

Mockito is a great library. It should be used extensively. But that doesn’t stop here. Mockito is a great source of inspiration for any developer who wants to improve his designing skills.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>