Intuitive Behavior Verification With Mockito

When first I learned the technique of using mock objects in unit tests it was a quite easy concept to grasp. The implementation was a little bit harder to understand though. The first mock objects framework I worked with was EasyMock and I didn’t find it very intuitive. Let me explain what I mean.

Here’s an example from EasyMock documentation. It checks that the documentAdded method is called on a mock listener when addDocument method is called on the tested class.

@Test
public void testAddDocument() {
    mock.documentAdded("New Document");
    replay(mock);
    classUnderTest.addDocument("New Document", new byte[0]);
    verify(mock);
}

Most people who see it for the first time have no idea what’s going on. The key to understanding it is realizing that the mock object has two states. Initially the mock is in a record state and saves method calls as expected behavior (line 3). Calling replay on the mock switches it to a replay state (line 4). After this the tested method is invoked (line 5). When some unexpected method is called on the mock object at this stage an exception is thrown by default. When you call verify you make sure that the expected methods were actually invoked (line 6). Otherwise an exception will be thrown. The record and replay states can be thought as an analogy to magnetic tape. This pattern is known as expect-run-verify and it’s quite popular in mock objects libraries.

I was wondering why I have to write as many as three lines of code scattered across my test to simply verify that a method was called on the mock. The way it was done in EasyMock and most other mock objects libraries at the time seemed like just too much hassle.

Fortunately, Szczepan Faber and his friends served Mockito. Here’s how I can rewrite the test using it:

@Test
public void testAddDocument() {
    classUnderTest.addDocument("New Document", new byte[0]);
    verify(mock).documentAdded("New Document");
}

In Mockito you ask about the interactions after exercising the tested method similarly to expressing assertions in standard tests. There are no two states to think about. It feels much more intuitive. It’s definitely the best mock objects library in Java I know.

To learn more about Mockito see its documentation.

Share
This entry was posted in Java and tagged , , , . Bookmark the permalink.

8 Responses to Intuitive Behavior Verification With Mockito

  1. Szczepan says:

    Looks like you are using *the right* libraries ;)

  2. Mocking imho does more harm than good.

    They are useless when refactoring since you not only need to refactor your code, but also the tests (and this means that you could introduce new bugs in your test).

    Often they tests get very long (much longer than 5/10 lines). So they don’t provide much insight in how an api should be used, since the tests are riddled with crap behind the implementation.

    Personally I see mocking in most cases as a damaging practice and should be discouraged.

    Doesn’t mean they are totally useless, but they are a very bad choice for 95% of the unit tests imho.

    Peter Veentjer
    Multiverse: Software Transactional Memory 4 Java
    http://multiverse.codehaus.org

  3. And last but not least, with mocking you still don’t know if your code really works. You only know that the assumptions you made in the code are repeated in the test.

  4. Peter, thank you for your comments. To some extend I agree with you. If you can test something without mocking, by all means do it. However, I think that there are cases when using mock objects is a good way to test otherwise hard to test code. For example, how would you write an unit test for a code that depends on current time without mocking a clock object? Or if there is no state to verify as in case of the test from the EaseMock documentation above, how would you test that the listener was notified?

    I’ve seen very long and brittle tests using mock objects. It’s a huge problem with expect-run-verify libraries that force you to specify all expected method calls at the beginning of the test. When you add another invocation in the tested class you have to refactor all the tests even if the new invocation is not related to the specific behavior you were intending to test. Also, it makes the tests much longer than they should be. I think in Mockito it’s much better because you can verify behavior selectively.

  5. Hi Pjoter,

    the time is indeed a good use case for mocking. More business related services often also a good candidates for mocking.

    But my experience is that teams go for 100% mocking and it makes code terrible. Another problem with a lot of mocking is that developers tend to test only a few flows since the tests get very long.

  6. I also disagree with 100% mocking approach.

  7. mP says:

    Using a mocking framework like mockito all fail when one attempts to refactor etc because of the use of magic strings to represent method names et al.

    If you have introduced interfaces then it should not be too much trouble to create anon inner classes within your tests and put the right asserts in the right spots.

  8. Actually, neither Mockito nor EasyMock uses strings to represent method names.

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>