Last Updated: February 25, 2016
·
4.32K
· lbehnke

Fake it till you make it

In Test-Driven Development by Example, Kent Beck suggests the principle "Fake it till you make it". Being a cornerstone of modern professional software development, unit testing is used across all common programming languages and development methodologies. There are many popular tools that support Java developers in writing unit tests.
In this posting I will compare the mocking libraries Mockito and EasyMock.
Both libraries gained popularity among Java developers in recent years.

EasyMock

EasyMock provides Mock Objects for interfaces by generating them on the fly using Java's proxy mechanism. It is open source software available under the terms of the Apache 2.0 license. Source code and downloads are hosted on SourceForge.
Issue tracking is done at Codehaus.
EasyMock is actively developend for more than seven years.
Version 3.1, that was released a couple of months ago, supports class mocking.

@Before
public void setup() 
{
    mocksControl = EasyMock.createControl();
    personDao = mocksControl.createMock(PersonDao.class);

    service = new PersonServiceImpl();
    service.setPersonDao(personDao);
}

In the example above we have two collaborating objects. A service instance uses a data access object to read person data
from a data store. Our test is supposed to focus on the service class. We do not want to test the DAO class and we have absolutely
no inclination to setup a test database.
So mocking the DAO object is the obvious thing to do.
Let's assume our service has a single method that returns the surnames
of all persons that start with a given letter. Optionally, the names are converted to
uppercase.

@Test
public void testFindLastNames1() throws Exception
{
    List<Person> persons = new ArrayList<Person>();
    persons.add(new Person("M.N.", "Thaler"));
    persons.add(new Person("Klaus", "Throphobie"));

    personDao.findPersons("T");
    EasyMock.expectLastCall().andReturn(persons);

    mocksControl.replay();

    List<String> names = service.findAllLastNames("T", true, true);

    mocksControl.verify();

    assertEquals(2, names.size());
    assertEquals("THALER", names.get(0));
    assertEquals("TROPHOBIE", names.get(1));
}

Note that EasyMock tests are divided into three sections.
First, the expected calls are recorded. And the mocked behaviour is defined. This phase is
finished by calling EasyMock.replay().
Now, the our test target is called, which in turn should playback the recorded statements on its
attached mock objects.
Finally, EasyMock.verify() makes sure our test target has called all expected methods with the right parameters.
If our test target returns a result, you may want to test it using assertions.

The above example expects the service to pass the filter string "T" to the DAO.
If any other letter is passed, the test will fail. If we wanted to allow any letter,
we would have to write code like this:

personDao.findPersons((String)EasyMock.anyObject());

If you choose this way to pass an argument, EasyMock expects you to implement an IAnswer interface, which gives
you a bit more flexibility in terms of argument validation and mocking behaviour.

EasyMock.expectLastCall().andAnswer(new IAnswer<List>() {
    public List answer() throws Throwable {
        String filter = (String)EasyMock.getCurrentArguments()[0];
        assertEquals("G", filter);

        Person person = new Person();
        person.setFirstName("Anna");
        person.setLastName("Gramm");
        List<Person> list = new ArrayList<Person>();
        list.add(person);
        return list;
    }
});

In case of an unexpected method calls EasyMock displays the following message:

java.lang.AssertionError: 
  Expectation failure on verify:
    PersonDao.findPersons("T"): expected: 1, actual: 0
    at org.easymock.internal.MocksControl.verify(MocksControl.java:183)
    at de.bdal.demo.service.PersonServiceImplEasyMockTest.testFindLastNames1(PersonServiceImplEasyMockTest.java:51)

Mockito

Mockito is much younger than EasyMock. It started off as an EasyMock fork but has
evolved in its own direction and now has a completely different API.
The Mockito team focused on readability and a pleasant coding experience.

@Before
public void setup() 
{
    personDao = Mockito.mock(PersonDao.class);
    service = new PersonServiceImpl();
    service.setPersonDao(personDao);
}

The setup of our test objects is as staight forward as with EasyMock.
The usage of the moching framework looks like this:

@Test
public void testFindLastNames1() throws Exception
{
    List<Person> persons = new ArrayList<Person>();
    persons.add(new Person("M.N.", "Thaler"));
    persons.add(new Person("Klaus", "Throphobie"));

    Mockito.when(personDao.findPersons("T")).thenReturn(persons);

    List<String> names = service.findAllLastNames("T", true, true);

    Mockito.verify(personDao, VerificationModeFactory.times(1)).findPersons("T");

    assertEquals(2, names.size());
    assertEquals("THALER", names.get(0));
    assertEquals("TROPHOBIE", names.get(1));
}

You may pass any String to mock object. In contrast of EasyMock you are not forced
to implement an answer interface.

Mockito.when(personDao.findPersons(Mockito.anyString())).thenReturn(persons);

Just for the sake of completeness: If you want to go the verbose way, you are allowed to do so.

when(personDao.findPersons(anyString())).thenAnswer(new Answer() {
    Object answer(InvocationOnMock invocation) {
        Object[] args = invocation.getArguments();
        [...]
    }
});

In case of an unexpected method call Mockito display the following stacktrace:

Wanted but not invoked:
personDao.findPersons("T");
-> at de.bdal.demo.service.PersonServiceImplMockitoTest.testFindLastNames1(PersonServiceImplMockitoTest.java:45)
Actually, there were zero interactions with this mock.

Conclusion

Both, EasyMock and Mockito, are powerful libraries that allow the same level of verification.
Verification errors are displayed in a clean and meaningful way by both candidates.
In terms of stability and quality I coundn't find any significant differences.
Both libraries are very stable and suitable for professional software development.

The Mockito code is a bit more readable. Mocking behaviour and verficiation is clearly separated.
Verification is explicit and optional. Developers may selectively verify certain method calls,
while others are simply mocked.

EasyMock code is quite verbose and less readable. Its record/playback concept couples
stubbing and verification step tightly. Although this concept is intuitive and quite easy to understand,
it forces the developer to deal with both aspects, which may lead to unnecessary verification code in some cases.
On the other hand, it is less probable that important verifications are forgotten.