Using EasyMock or Mockito

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.

Reference: using EasyMock or Mockito from our JCG partner Rahul Sharma at the The road so far… blog blog.

Related Whitepaper:

Bulletproof Java Code: A Practical Strategy for Developing Functional, Reliable, and Secure Java Code

Use Java? If you do, you know that Java software can be used to drive application logic of Web services or Web applications. Perhaps you use it for desktop applications? Or, embedded devices? Whatever your use of Java code, functional errors are the enemy!

To combat this enemy, your team might already perform functional testing. Even so, you're taking significant risks if you have not yet implemented a comprehensive team-wide quality management strategy. Such a strategy alleviates reliability, security, and performance problems to ensure that your code is free of functionality errors.Read this article to learn about this simple four-step strategy that is proven to make Java code more reliable, more secure, and easier to maintain.

Get it Now!  

Leave a Reply


− six = 3



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

15,153 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books