Trifork Blog

Easier mocking with Mockito

August 13th, 2009 by
| Reply

If you have been happily using Easymock for the past years, this blog post is for you. Because you need to upgrade to Mockito, the new kid on the block in the mocking universe. Why bother about what mocking framework you're using to create your unittests? Because it will improve you tests, make them more expressive, and help you write better code. Read on if you want to know more. 

The EasyMock way

Here's what a unittest typically looks like with Easymock:

import org.junit.*;
import static org.junit.Assert.*;
import static org.easymock.EasyMock.*;
// More imports...

public class ServiceFacadeTest {

    /** Pass condition: commits the service and returns the result. */
    @Test
    public void testService() throws Exception {
        Service serviceMock = createMock(Service.class);
        ServiceFacade serviceFacade = new ServiceFacade(serviceMock);

        ServiceRequest request = new ServiceRequest();
        ServiceResult result = new ServiceResult();

        expect(serviceMock.execute(request)).andReturn(result);
        serviceMock.commit();

        replay(serviceMock);

        ServiceResult actualResult = serviceFacade.service(request);

        verify(serviceMock);

        assertSame(result, actualResult);
    }

// More tests...
}

I won't go into the details of the class under test, or the classes it interacts with. I shouldn't need to. The unittest itself should be self-contained, and you should be able to read it as a specification of the behavior under test. After all, following TDD best practices, I usually write the test before implementing the behaviour, so this is a good place to specify what it should do. Let's go over it line-by-line:

1 - By convention, the name of the test class specifies the name of the class under test, which is ServiceFacade.

2 - Also by convention, the name of the test method specifies the name of the method under test, which is service().

3 - Another convention I use, is to specify the test's pre- and pass conditions in the method Javadoc. In this case, no precondition is specified, indicating that we're currently testing typical behaviour, the "happy path", as opposed to exceptional- or corner case behaviour. (I'll come back to that.)

4 - The pass condition specifies the criteria for the test to pass. We already know that what method we're testing, so there's no need to restate that as part of the pass condition.

So, putting everything together, we're testing ServiceFacade method service(), and the test will pass when it commits the service and returns the result.

So far, we haven't seen what this service is about. This becomes apparent when we inspect the first lines of code in our test.

        Service serviceMock = createMock(Service.class);
        ServiceFacade serviceFacade = new ServiceFacade(serviceMock);

5 - A Service mock is created, and passed on to the ServiceFacade constructor. Clearly, the class under test, ServiceFacade, needs a Service instance to do its job.

6 - We use EasyMock to create the Service instance that we provide to the constructor. As you might expect, the way the class under test interacts with the service is what this test is all about.
The expected interaction is coded in the next lines before we call replay() on the mock:

        ServiceRequest request = new ServiceRequest();
        ServiceResult result = new ServiceResult();

        expect(serviceMock.execute(request)).andReturn(result);
        serviceMock.commit();

We expect the service method execute()to be called with a request, and tell it to return a result. In addition we expect its (void) commit() method to be called.

7 - Next, we set to mock to the replay mode, call the method under test, and verify that the expected method calls were executed:

        replay(serviceMock);

        ServiceResult actualResult = serviceFacade.service(request);

        verify(serviceMock);

8 - Finally, we assert that the method under test returned the result we expect, which is the result previously returned by the service:

        assertSame(result, actualResult);

The Good...

So far, so good. Once you're used to the EasyMock idiom, it does a good job of providing us with a way to specify the behaviour of the code under test. But, actually, it did more than just that.

The Bad: overspecification

On closer inspection, we specified more than what is relevant for our test.

First of all, the way we created the service mock relies on Service to be an interface. For the behaviour under test, it might as well have been a concrete class, but in that case we would have to import EasyMock from the org.easymock.classextension package instead, and add easymockclassextension.jar to the test's classpath.

Secondly, the Service method commit() must be a void method. If it would actually return something, EasyMock would require us to explicitly specify the value it returns, even though the returned value would be irrelevant for the behaviour under test.

These are two examples of overspecification in our test. Details about Service have leaked into the testing code. Later on we might apply refactorings that break these assumptions, and they will break this test. Consequently we will be forced to update the testing code in response to changes that are not relevant to the behaviour under test! This is Bad: our test is more fragile that it needs to be, and obviously this is something we want to avoid.

Also, and worse, we need to explicitly set expectations for each method we call on the Service. Again, even when it is not relevant for the logic under test. E.g. when there is a debug-level logging statement that calls a method on the service (say service.getName(). This opens up the possibility for our test to fail depending on our logging configuration!

The Ugly...

Let's have another look at those lines of code that specify our expectations:

        expect(serviceMock.execute(request)).andReturn(result);
        serviceMock.commit();

The EasyMock idiom does a good job of making the expectation explicit for a method call that returns a result (the first line). But specifying an expectation for a void method just looks like an ordinary method call (the second line). When dealing with EasyMock, the only way to only way to see the difference between setting an expectation and actually calling the method for void methods is by looking if they are before or after the line where replay() is called for that mock. Note that I named my mock serviceMock to make this more explicit. Still, I think this is confusing and inappropriate.

The Mockito way

Now here's what the same test would look like using Mockito:

import org.junit.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
// More imports...
import nl.robvanmaris.blog.ServiceFacade;

public class ServiceFacadeTest {

    /** Pass condition: commits the service and returns the result. */
    @Test
    public void testService() throws Exception {
        Service service = mock(Service.class);
        ServiceFacade serviceFacade = new ServiceFacade(service);

        ServiceRequest request = new ServiceRequest();
        ServiceResult result = new ServiceResult();

        when(service.execute(request)).thenReturn(result);

        ServiceResult actualResult = serviceFacade.service(request);

        verify(service).commit();

        assertSame(result, actualResult);
    }

// More tests...
}

Let's go over the differences, again line-by-line:

1 - Creation of the mock:

        Service service = mock(Service.class);

With Mockito this will work regardless of whether Service is an interface of a concrete class. The latter is not relevant for the purpose of the test, and Mockito does not force us to make this explicit.

2 - For the logic under test, we tell the mock how to behave. I.e. when its execute() method is called with the given request, it should return the given response. It looks as simple as this:

        when(service.execute(request)).thenReturn(result);

3 - Next we call the method under test, and subsequently verify that commit() was called.

        ServiceResult actualResult = serviceFacade.service(request);

        verify(service).commit();

Other than in the EasyMock example, the Mockito idiom makes it explicit that we're specifying an expectation here, as a opposed to making a regular method call on the service. Because setting expectations is so explicit, I've chosen to name the variable service instead of serviceMock. There's no need to make it more explicit that the variable represents a mock object, since the Mockito idiom already takes care of this.

4 - Finally, we assert that the method under test returned the result we expected.

        assertSame(result, actualResult);

5 - Why didn't we verify that the execute() method was called on the mock? We certainly could have added this line, and it would have worked.

        verify(service).execute(request);

But was definitely better to have this left out. There is simply no way that the assertion at the end, i.e. the method under test returned the expected result, can pass without the service execute() method being called as expected. Since there's no need to make this verification more explicit, we better leave it out, so we have fewer lines of code with the same expressive power.

Stubbing versus mocking

One thing you have to understand to get started with Mockito is the difference between a stub and a mock.

A stub is an object that is set up to feed the required inputs into the system under test. In our case we do this by telling the object how to respond to various inputs. E.g. by telling it to return an object in response to a method call. This is reflected by Mockito's when(...).thenReturn(...) idiom. There are similar options to tell the stub to throw an exception.

A mock is an object that is used to verify if the system under test interacts as expected with objects it relies on. Mockito's verify(...).methodXxx(...) idiom does just that: it verifies if methodXxx(...) was called as expected.

Now that we have defined mocks and stubs, it becomes apparent that mocking frameworks produce so-called mock objects that are used as both mock and stub. I.e. they are both set-up to produce expected responses and to verify that the system under tests interacts with them as expected. At closer inspection, it's this difference between stubbing and mocking is what sets EasyMock and Mockito apart.

With EasyMock, the difference between stubbing and mocking is blurred, since its expect(...) idiom both specifies the mocks behaviour as well as expectations.

Mockito, on the other hand, differentiates explicitly: when(...).then(...) for specifying stub behaviour, and verify(...).methodX(...) for specifying mock expectations.

Why should we care? By now it should be quite obvious. The Mockito test more accurately expresses its intentions. It specifies more precisely what we want to specify, and it doesn't specify more than we want. It does not overspecify. But there is one more thing you need to be aware of.

The unspecified

By now, you might wonder about interactions that are not specified. To avoid overspecification, we allow methods to be called on the mock that we didn't tell it how to respond to. Other than EasyMock, Mockito handles these calls silently without complaints. These calls return null, 0 or false depending on the method's return type. A side-effect of this is that these values may pop up in a failing test, as well as a NullPointerException. You need to be aware that these values are a result of the mock being called other than expected.

Mockito best practices

In my experience, Mockito is easier and nicer to use than EasyMock. Coming from EasyMock, you need to keep these things in mind:
- Don't verify stubbed methods, unless you need to. As in the example, the stubbed methods usually need to be called for the test to pass, without explicit verification. There is one important exception: an unstubbed method will return null, 0 or false. If that is the return value that you tell the mock to return, you should also explicitly verify the method was called, otherwise there is no way to be sure the method was actually called as expected.
- Beware of null, 0, false and NullPointerExceptions. When these values pop up in a failing test, it could indicate that the mock was called in a way you did not expect.

Exceptional cases

Finally, since I promised, here's an example of a test for exceptional behaviour, i.e. the service throws an exception. As you can see, this is just as straight-forward and easy to understand.

    /**
     * Pre condition: service execution throws an exception.
     * Pass condition: rolls back the service and throws RuntimeException that wraps the original ServiceException.
     */
    @Test
    public void testService_throwsException() throws Exception {
        Service service = mock(Service.class);
        ServiceFacade serviceFacade = new ServiceFacade(service);

        ServiceRequest request = new ServiceRequest();
        ServiceException exception = new ServiceException();

        when(service.execute(request)).thenThrow(exception);

        try {
            ServiceResult result = serviceFacade.service(request);
            fail("Should throw RuntimeException");
        } catch (RuntimeException e) {
            assertEquals(exception, e.getCause());
        }

        verify(service).rollback();
    }

Conclusion

I hope you can see by now why Mockito is a better alternative to EasyMock. At JTeam we're adopting Mockito in all our new projects. And whenever we have to go back to EasyMock, in the code from earlier projects, we know it was a good move. Happy mocking!

14 Responses

  1. August 14, 2009 at 00:37 by Rogério Liesenfeld

    In EasyMock, it's not true that "we need to explicitly set expectations for each method we call on the Service".

    If you create a "nice" mock instead, with "Service serviceMock = createNiceMock(Service.class);", then unrecorded invocations will be allowed. For example, if the line "serviceMock.commit();" is removed, the test will still pass.

  2. August 14, 2009 at 07:32 by Stevo Slavic

    Great article, thanks for sharing!

    Have you noticed any cons so far?

    Mockito (with a little help of a DI container like Spring) seems to allow writing tests based on interfaces only (so to test the behavior and not to have them polluted with the implementation details), and then reuse tests for verifying any implementation. Do you agree?

  3. August 14, 2009 at 22:48 by Peter Niederwieser

    Here is how you would describe the exceptional case with Spock:

    def "if execution of request fails, facade triggers rollback and propagates failure"() {
    def service = Mock(Service)
    def serviceFacade = new ServiceFacade(service)

    def request = new ServiceRequest()
    def exception = new ServiceException()

    service.execute(request) >> { throw exception }

    when:
    serviceFacade.service(request)

    then:
    1 * service.rollback()
    RuntimeException e = thrown()
    e.cause == exception
    }

  4. August 15, 2009 at 08:42 by Jettro Coenradie

    Very nice post, gives me more reasons to abandon easymock.

    thanks

  5. August 15, 2009 at 11:12 by Richard Paul

    Good write up, I switched from EasyMock to Mockito a while ago and have never looked back. The main benefits are definitely test readability and avoiding over constraining of tests.

    Mockito 1.8 also introduced BDD style aliases for those interested. e.g. given(...).willReturn(...) instead of when(...).thenReturn(...)
    http://www.rapaul.com/2009/08/09/bddmockito-eclipse/

  6. August 16, 2009 at 10:55 by Rob van Maris

    Rogério, you're right. EasyMock does provide createNiceMock(...) to prevent overspecifying method calls, but this feature is relatively unknown. "Nice Mock" is not quite self-explanatory, and the documentation treats it as a highly advanced feature. As a result it is little used, and developers are discouraged to pay more attention to the risks of overspecification.
    Mockito, on the other hand, makes this "nice mock" the standard approach, much to its credit.

  7. [...] Easier mocking with Mockito « JTeam Blog / JTeam: Enterprise Java, Open Source, software solut... – I hope you can see by now why Mockito is a better alternative to EasyMock. At JTeam we’re adopting Mockito in all our new projects. And whenever we have to go back to EasyMock, in the code from earlier projects, we know it was a good move. Happy mocking! [...]

  8. [...] Easier mocking with Mockito [...]

  9. [...] van Maris’ blog post titled Easier mocking with Mockito describes how to use Mockito and how it compares to [...]

  10. December 2, 2009 at 17:58 by Julian

    Here's an interesting consequence of those default return values: null, 0 and false.

    The equals() method on Mockito mock objects will return 0, so adding separate mock objects to a Set results in a just one of them in the Set, the others excluded because they're all technically equal. Surprising if you expected the default identity equals of Object. Still, it's an easy behaviour to explain and it's consistent, and there are solutions to the equals problem, so a reasonable choice on balance.

    I've previously used both EasyMock and JMock, and while I'm still in my first dozen classes developed with Mockito, it seems a solid alternative with some real benefits.

  11. December 21, 2009 at 11:40 by Rony

    Very good post!

  12. June 28, 2010 at 20:31 by Petri

    I ended up here via Google, and I must say that this blog post is exactly what I have been looking for. I have been using Easymock for years in my projects, but recently I have been starting to investigate Mockito as its replacement. This is a very good explanation about their differences, and I am going to share this with my colleagues. Keep up the good work!

  13. July 9, 2010 at 15:41 by Mihir

    How to write test cases for DAO layer in a Sruts applicaiton using Mockito?

  14. August 24, 2010 at 10:06 by camestres.com » Links for 13/8/2010

    [...] Easier mocking with Mockito « JTeam Blog / JTeam: Enterprise Java, Open Source, software solut... – Share and Enjoy: [...]

Leave a Reply