Mockito

open sourced testing framework


17 Jun 2017 View Comments
#mockito #testing #framework #mock

Mockito is a popular open-sourced Java mocking framework which is used for testing. The idea of mocking is widespread out in many other languages because it is indeed useful and essential for creating unit tests.

Mockito? what is it?

You may be unfamiliar with the term, mock. A mock is like creating a disguised thing that behaves like the real thing which can execute given instructions. The Mockito is a tool to do just that. A mock would not actually create any real object so it just creates a type of a thing you are mocking.

For example (using the famous list example):

Let’s take a look at the example of what I mean by creating a type. testIntsMock is a mock object of a List:

@Test
public void testListMock()
{
    testIntsMock.add(30);
    testIntsMock.add(20);
    testIntsMock.add(10);
    verify(testIntsMock).add(10);

    assertEquals(0, testIntsMock.size());
}

Note the mocked list (testIntsMock) did not actually add any values but we’ve successfully verified that the add operation is called which ensures us that functionally it is doing what it supposed to do.

Let’s say that we wanted actual behavior changes with the mocked item. The Mockito supports this as well. We can use Spy instead of plain Mock to do our mocking:

@Test
public void testListSpy()
{
    testIntsSpy.add(30);
    testIntsSpy.add(20);
    testIntsSpy.add(10);
    verify(testIntsSpy).add(10);
    when(testIntsSpy.get(1)).thenReturn(50);

    assertEquals(3, testIntsSpy.size());
    assertTrue(30 == testIntsSpy.get(0));
    assertTrue(50 == testIntsSpy.get(1));
}

Note the Spy list is now has the actual size 3 instead of 0 from our Mock example. So why use Spy? Well, the example above revealed already a couple of powerful mocking ability the Spy can do instead of using a real object. You can manipulate the spied object using when/doAnswer etc. Also, you can make verify calls to ensure the function you are testing is working.

Examples

Examples are available and found easily online. It is redundant to duplicate their work here. I would encourage you to look for examples or examples are found in various tests in src/test of my Java algorithm playground

Best Practices using Mockito

  1. Unit tests vs Functional Tests

    Mockito is mainly written for unit tests which enable you to write tests for each function separately. It creates mocked types which essentially may be ignored for testing DAO (DB object) or streams (compression, file, iterators, a flow of data) or rendering or anything that might require complicated work, you can abstract those using mocks. In an ideal testing environment, we can have unit tests testing on every change as part of CI then those complicated work can be tested via functional tests (which also can be as part of CI) running every night. In my opinion, this is a good testing layout which will ensure end-to-end functionalities are also covered for testing as well as the unit tests which will be just a quick tests via Mocking.
  2. Know your tests and provide compact and readable tests

    This one is an obvious item. You are not going to write good unit tests using various mocking abilities without knowing exactly what is happening in the code you are trying to mock. For example, you should not simply mock string encode operation when the operation is expected to be done as part of the function. Also, when you are mocking an item. You need write tests as precise and readable as you can because tests with mocking can easily lose tracks and change behaviors upside down quite easily. It will not only help others but most importantly it will help you who will eventually write the tests out. Writing clean and neat tests are for you, not for others.
  3. Be aware of mocking types you don't own

    This is something programmers often look down. They do not find this important as they use trusted 3rd party libs that won't dramatically change their behaviors. This is a big mistake though. I have seen many libs which changed its behaviours drastically that the mocked tests would still pass as we have mocked the the entire 3rd party lib function. It is usually wrong and dangerous thinking to assume things will behave the way it is. For 3rd party libs, we have associated versions in dependency list to make sure behaviour stick to the way the software is expecting. So there will be a time when the version will need to go up. Now, let's say we reviewed over all of its changelogs carefully. Does this mean we will remember how its usage been written in every test? Wouldn't it be safer to not mock any of its behaviours so we have the red flags (errors) when running the tests?

Useful Mockito Usage

I find the following Mockito functionalities most useful at least from my experiences. It is definitely worth mentioning here.

  • Answer

    Answer is a powerful mockito behavior which enables an idea of callbacks when things are called. This is very useful if you are wish to change the behaviours of a specific function of an another mocked object. 2 Examples on how I use Answers:
when(extractor.extract(eq(in))).thenAnswer(new Answer<String>() {
    @Override
    public String answer(InvocationOnMock invocation) throws Throwable {
        InputStream in = Util.getInputStream(filename, Parser.class);
        return new String(IOUtils.toByteArray(in));                              
    }
}); 

Or you can also have when at the end using doAnswer:

doAnswer(new Answer<ReturnValueObject>() {
    @Override
    public ReturnValueObject answer(final InvocationOnMock invocation) throws Throwable {
        final Integer originalAmount = (invocation.getArguments())[0];
        final Integer chargedAmount = (invocation.getArguments())[1];
        final ReturnValueObject returnedValue = new ReturnValueObject();
        returnedValue.setCost(new Cost(originalAmount - chargedAmount));
        return returnedValue;
    }
}).when(priceChangeRequestService).quickCharge(any(Integer.class), any(Integer.class));
  • Inorder

    Inorder is a great way to verify order / sequence of method calls. Here is an example usage as examples are better than 1000 words:
ServiceClassA firstMock = mock(ServiceClassA.class);
ServiceClassB secondMock = mock(ServiceClassB.class);

Mockito.doNothing().when(firstMock).methodOne();   
Mockito.doNothing().when(secondMock).methodTwo();  

//create inOrder object passing any mocks that need to be verified in order
InOrder inOrder = inOrder(firstMock, secondMock);
inOrder.verify(firstMock).methodOne();
inOrder.verify(secondMock).methodTwo();

This will make sure that firstMock’s methodOne is called before secondMock’s methodTwo is invoked.

  • Capture

    You can use mockito's capture ability to capture any values you need to assert later. Here is an example from Mockito's javadoc:
ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
verify(mock).doSomething(argument.capture());
assertEquals("John", argument.getValue().getName());

Above will capture the object, Person, which would let you use it to assertValues are what you expected at the end.

This is very useful as there are times where you would like the Mockito to capture the value as they are being verified which later you will be able to assert.

Share this post

Me

I am a passionate software developer working in Downtown, Vancouver. I strongly believe in art of algorithms and together with it to write clean and efficient software to build awesome products. If you would like to connect with me, choose one from below options :) You can also send me an email at