The road so far….

January 9, 2011

using EasyMock or Mockito

Filed under: Agile, java — Rahul Sharma @ 8:36 pm

I have been using EasyMock for most of time but recently I worked with a few people who were pretty much inclined to use Mockito. Not intending to use two frameworks for the same purpose in the same project I adopted Mockito.  So for the last couple of months I have been using Mockito and here is my comparative analysis of the  two.

The  people with whom I have work cite reasons of test readability for using Mockitio but I have a different opinion on the same.  Suppose we have the following code that we intend to test :

public class MyApp {
    MyService service;
    OtherService otherService;

    void operationOne() {
        service.operationOne();
    }

    void operationTwo(String args) {
        String operationTwo = otherService.operationTwo(args);
        otherService.operationThree(operationTwo);
    }

    void operationThree() {
        service.operationOne();
        otherService.operationThree("success");
    }
}

class MyService {
    void operationOne() {}
}

class OtherService {
    public String operationTwo(String args) {
        return args;
    }

    public void operationThree(String operationTwo) {}
}

Now let me write a simple test case  for this class using EasyMock and the using Mockito.

 public class MyAppEasyMockTest {
    MyApp app;
    MyService service;
    OtherService otherService;

    @Before
    public void initialize() {
        service = EasyMock.createMock(MyService.class);
        otherService = EasyMock.createMock(OtherService.class);
        app = new MyApp();
        app.service = service;
        app.otherService = otherService;
    }

    @Test
    public void verifySimpleCall() {
        service.operationOne();
        EasyMock.replay(service);
        app.operationOne();
        EasyMock.verify(service);
    }
 }
public class MyAppMockitoTest {
    MyApp app;
    MyService service;
    OtherService otherService;

    @Before
    public void initialize() {
        service = Mockito.mock(MyService.class);
        otherService = Mockito.mock(OtherService.class);
        app = new MyApp();
        app.service = service;
        app.otherService = otherService;
    }

    @Test
    public void verifySimpleCall() {
        app.operationOne();
        Mockito.verify(service).operationOne();
    }
 }
 

This is a really simple test and I must say the Mockito one is more readable . But  according to the classic testing methodology the Mockito test is not complete. We have verified the call that we are looking for but if tomorrow I change the source code by adding one more call to service  the test would not break.

 void operationOne() {
        service.operationOne();
        service.someOtherOp();
  }

Now this makes me feel that the tests are not good enough. But thankfully Mockito gives the verifyNoMoreInteractions that can be used to complete the test. Now let me write a few more test for the MyApp class.

public class MyAppEasyMockTest {
      @Test
    public void verifyMultipleCalls() {
        String args = "one";
        EasyMock.expect(otherService.operationTwo(args)).andReturn(args);
        otherService.operationThree(args);
        EasyMock.replay(otherService);
        app.operationTwo(args);
        EasyMock.verify(otherService);
    }

    @Test(expected = RuntimeException.class)
    public void verifyException() {
        service.operationOne();
        EasyMock.expectLastCall().andThrow(new RuntimeException());
        EasyMock.replay(service);
        app.operationOne();
    }

    @Test
    public void captureArguments() {
        Capture<String> captured = new Capture<String>();
        service.operationOne();
        otherService.operationThree(EasyMock.capture(captured));
        EasyMock.replay(service, otherService);
        app.operationThree();
        EasyMock.verify(service, otherService);
        assertTrue(captured.getValue().contains("success"));
    }

}

public class MyAppMockitoTest {
    @Test
    public void verifyMultipleCalls() {
        String args = "one";
        Mockito.when(otherService.operationTwo(args)).thenReturn(args);
        app.operationTwo(args);
        Mockito.verify(otherService).operationTwo(args);
        Mockito.verify(otherService).operationThree(args);
        Mockito.verifyNoMoreInteractions(otherService);
        Mockito.verifyZeroInteractions(service);
    }

    @Test(expected = RuntimeException.class)
    public void verifyException() {
        Mockito.doThrow(new RuntimeException()).when(service).operationOne();
        app.operationOne();
    }

    @Test
    public void captureArguments() {
        app.operationThree();
        ArgumentCaptor capturedArgs = ArgumentCaptor
                .forClass(String.class);
        Mockito.verify(service).operationOne();
        Mockito.verify(otherService).operationThree(capturedArgs.capture());
        assertTrue(capturedArgs.getValue().contains("success"));
        Mockito.verifyNoMoreInteractions(service, otherService);
    }
}

These are some practical scenarios of testing where we would like to assert arguments, Exceptions etc. If I look and compare the ones written using EasyMock with the ones using Mockito I tend to feel that both the tests are equal in readability, none of them do a better task.

The large number of expect and return calls in EasyMock make the tests not readable and  the verify statements  of Mockito often compromise over test readility. As per the documentation of Mockito the verifyZeroInteractions, verifyNoMoreInteractions should not be used in every test that you write but if  I  leave them out of my tests then  my tests are not good enough.

Moreover in tests everything thing should be under the control of the developer i.e. how the interaction are happening and what interactions are happening. In EasyMock this aspect is more visible as the devloper must put down all of these interaction in his code but in Mockito, the framework takes care of  all interactions and the developer is just concerned with their verification ( if any). But this can lead to testing scenarios where the developer is not under control of all interactions.

There are few nice things that Mockito has like the  JunitRunner that can be used to create Mocks of all the required dependencies. It is a nice way of removing some of the infrastructure code and EasyMock should also have one.

@RunWith(MockitoJUnitRunner.class)
public class MyAppMockitoTest {
    MyApp app;
    @Mock
    MyService service;
    @Mock
    OtherService otherService;

    @Before
    public void initialize() {
        app = new MyApp();
        app.service = service;
        app.otherService = otherService;
    }
}

Conclusion:

Since  I have used both frameworks, I feel that except for simple test cases both EasyMock and Mockito lead to test cases that equal in readability. But EasyMock is better for the unit testing as it forces the developer to take control of things.  Mockito due to its assumptions and considerations hides this control under the carpet and thus is not a good choice. But Mockito offers certaing things that are quite useful(eg. junitRunner, call chaining) and EasyMock should have one in its next release.

About these ads

15 Comments »

  1. [...] use two frameworks for the same purpose in the same project I … Continue reading →… [full post] Rahul Sharma The road so far…. agilejava 0 0 0 0 [...]

    Pingback by using EasyMock or Mockito — January 10, 2011 @ 12:32 am

  2. Regarding your conclusion, I think there is another reading of how Mockito works – yes, the resulting tests are indeed more flexible, but that not a bad thing. On the contrary, the tests are far less brittle and allow each test to only focus on one single piece of logic – the logic under test. Yes, other things may be going on, but that’s not the concern of that particular test. With EasyMock, the test will end up much more fragile, as almost any change to the code base will end up breaking a lot of tests, and what’s worse, it will break them for reasons that have nothing to do with the actual tests. So I see Mockito’s choice of not forcing you to over specify as a good one from this very important point of view. This is not to mention that the Mockito tests are far more readable.
    Just my 2 cents.
    Eugen.

    Comment by Eugen Paraschiv — January 12, 2011 @ 4:33 pm

  3. good article, I agree with you, however I prefer EasyMock, because of the methods names(thenReturn vs andReturn). Plus as you say you don’t need to verify mocks with EasyMock.

    Beside that I’m too lazy to learn another mocking frameworks that gives me nothing new except one less line of code(if you don’t count verify, so its gives me nothing) for mock.

    Comment by raveman — January 12, 2011 @ 6:21 pm

  4. One really cool think about Mockito is the name, it sounds cooler, I will admit that. But should you rewrite all your custom mocks to be cool?

    Comment by raveman — January 12, 2011 @ 6:23 pm

    • No, it is not a good idea to rewrite your existing mocks using any cool framework. But you can always decide and use it for you new tests. IMHO your team should decide on one mocking framework and then should follow it.

      Comment by Rahul Sharma — January 12, 2011 @ 9:31 pm

  5. Hey, have you tried JMockit? Is another good choice.

    Comment by Victor — January 12, 2011 @ 7:05 pm

    • No, I have no knowledge of JMockit.

      Regards

      Comment by Rahul Sharma — January 12, 2011 @ 9:28 pm

  6. You do not need ArgumentCaptor in above example.

    Instead of three lines to capture string:
    ArgumentCaptor capturedArgs = ArgumentCaptor
    .forClass(String.class);
    Mockito.verify(otherService).operationThree(capturedArgs.capture());
    assertTrue(capturedArgs.getValue().contains(“success”));

    you can just write Mockito.verify(otherService).operationThree(StringContains.containsString(“success”));

    My suggestion is to use static imports for all methods here, which would make this test even better:

    verify(otherService).operationThree(containsString(“success”));

    This would make mockito test shorter and more readable

    Comment by Tomasz Bartczak — January 12, 2011 @ 8:16 pm

  7. I must admit that I am a Mockito fun. I had no readability or control issues with Mockito. That is why, I must admit that I do not understand this conclusion: “Mockito due to its assumptions and considerations hides this control under the carpet and thus is not a good choice.”
    Can you elaborate on this? Where exactly you have no control? What you can do with EasyMock and can’t do with Mockito?

    Thanks!

    Comment by Alexandru — January 12, 2011 @ 8:21 pm

    • I meant to say that in EasyMock you have to write every possible interaction with mock else it will not work. In Mokito you need not to do so. You can do such a thing using verification but IMO as developers we are too lazy to do this if the framework does not enforce it. Also if we do not do verify every possible interaction then the tests are not good enough because tomorrow I can add a new interaction and the test wold not break.

      Comment by Rahul Sharma — January 12, 2011 @ 9:23 pm

      • In answer to that I will repeat a point that has been made more than once in this thread. The fact that Mockito doesn’t automatically verify EVERY interaction is WHY it’s better than EasyMock. Your test should be verifying the documented and required functionality of the code under test, not unimportant side effects.

        Comment by David M. Karr — January 12, 2011 @ 10:27 pm

  8. I have no previous experience of either Mockito or EasyMock but have used JMock – reading this I believe it is significantly better than either and suggest you try it. It gives you the same control more flexibly and much more readably.

    Comment by Jason Turner — February 1, 2011 @ 6:22 pm

  9. [...] You Think Face Detection in Java – Haar Cascade with JJIL (how-to) Scrum developers’ glossary Using EasyMock or Mockito Agile Thinking Hudson Project Renames to Jenkins Continuous Delivery Breaking Down Walls, Building [...]

    Pingback by TapaGeuR » ITGIF – “IT-God” It’s Friday #22 — February 20, 2011 @ 12:04 am

  10. [...] This post describes some guy’s experience with both toolkits (Mockito and EasyMock). [...]

    Pingback by Choosing a Unit Testing framework « Amir Zucker's knowledge zone — October 3, 2012 @ 12:45 am

  11. … [Trackback]

    [...] Informations on that Topic: devlearnings.wordpress.com/2011/01/09/using-easymock-or-mockito/ [...]

    Trackback by URL — September 17, 2014 @ 7:28 am


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The Shocking Blue Green Theme. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: