Mockito is an open source testing framework for Java that allows the creation of test double objects in automated unit tests for the purpose of test-driven development or behavior-driven development.
Test Double is generic term used by Gerard Meszaros to mean any case where you replace a production object for testing purposes.
- Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
- Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an InMemoryTestDatabase is a good example).
- Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what’s programmed in for the test.
- Spies are stubs that also record some information based on how they were called. One form of this might be an email service that records how many messages it was sent.
- Mocks are pre-programmed with expectations which form a specification of the calls they are expected to receive. They can throw an exception if they receive a call they don’t expect and are checked during verification to ensure they got all the calls they were expecting
Most of the time the code we write have dependencies. Often, delegates some work to other methods in other classes. If we are to use Unit testing, our test has to depend on those methods, but we want the tests to be independent of all other dependencies. We need a way to isolate a unit of code and test it alone.
There are different ways of adding Mockito into your project, below are some of the common ways.
- Download the jar file and at it to our project path.
- Add the dependency to the build automation tool that you are using in your project. E.g.
// Maven Dependency
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
// Gradle Dependency
testCompile “org.mockito:mockito−core:1.9.5“
// Ivy Dependency
<dependency org=”org.mockito” name=”mockito-core” rev=”1.9.5” conf=”test->default”/>
After adding the dependencies in our project what next?
Asuming we want to test a class in our application, we first create and inject the depencies using either annotations or Mockito’s static method mock()
The example below illustrate the use of Mockito without annotations to create and inject mocks.
private EtcBaseDao etcBaseDao;
private EtcBaseService etcBaseService;
@Before
public void setUp() {
etcBaseDao = Mockito.mock(EtcBaseDao.class);
etcBaseService = new EtcBaseService(etcBaseDao);
}
refer to com.etcbase.mockito.service.MockitoWithoutAnnotationTest.java in the source code for complete example.
The example below illustrate how to use Mockito’s annotation to create mock instances and inject them using the follwing annoations.
- @Mock will create a new mock implementation for the given class.
- @InjectMocks will inject the created mock to given class instance.
// The method is called before the execution of every test in the test class.
@Mock // create a new mock implementation
private EtcBaseDao etcBaseDao;
@InjectMocks // inject the created mock instances in this class.
private EtcBaseService etcBaseService;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this); // This line create an instance and insert all the mock dependencies.
}
refer to com.etcbase.mockito.service.MockitoWithAnnotationTest.java in the source code for complete example.
Some times litle thing can become boring, if you are tired of using the above way of satisfying dependencies you can add MockitoJUnitRunner or use MockitoJUnit4Runner from Spring in your test, it will take care of that. If you are using spring test, then you already have it. You can use it. Below is example using MockitoJUnit4Runner.
@Runwith(MockitoJUnit4Runner.class)
public class MockitoJUnit4RunnerTest {
@Mock
private EtcBaseDao etcBaseDao;
@InjectMocks
private EtcBaseService etcBaseService;
}
Mockito heavely uses static methods such as the once shown below.
METHOD | DESCRIPTION |
---|---|
thenThrow(Throwable toBeThrown) | Throws given exception |
thenThrow(Class<? extends Throwable> toBeThrown) | |
then(Answer answer) | Uses user-created code toanswer |
thenAnswer(Answer answer) | |
thenCallRealMethod() | Calls real method when working with partial mock/spy |
thenReturn(returnValue) | Return the given value |
The ability to return a test double as value when a method is called is called Stubbing. With Mockito you can specify how and what a method should return when it’s called e.g. using Mockito.when() with thenReturn()
The following arrange-act-assert pattern (similar to given-when-then, from Behavior Driven Development) a test should be splited into three parts (blocks) each with a specify responsibility.
//////////// Given then above behavior driven development Mockito also has BDDMockito class that introduces BDD semantics.
After creating and injecting your mock, you should then tell Mockito how to behave when certain method are invoked.
Mockito.when(instanceName.methodName(methodArguments)).thenReturn(true); // return true when the instance method is called.
Mockito.when(etcBaseService.save(etcBase)).thenReturn(etcBase);
refer to com.etcbase.mockito.service.MockitoWhenThenReturnTest.java in the source code for complete example.
We can also use matchers as shown below.
Mockito.when(etcBaseService.save(Mockito.any(EtcBase.class))).thenReturn(etcBase);
However, if there are more than one parameters in a method we cannot mix matchers and actual objects. We either have to use matcher for the parameters, or real objects and values.
Mockito.when(etcBaseService.getByIdAndDate(branchId, Mockito.any(Date.class))).thenReturn(etcBase); // this will throw exception.
refer to com.etcbase.mockito.service.MockitoMatcherTest.java in the source code for complete example.
- You should use thenReturn() or doReturn() when you already know the return value at the time you mock the method call.
- You should use Answer() or doAnswer() when you need to do additional things when a mocked method is invoked.
- There is no much difference between must of Hamcrest matchers and junit asserts, only that hamcrest tends to given more information when there is an error with the test method.
We can use the JUnit expected to make sure that a method throw exception when it’s called.
@Test(expected = ExceptionName.class)
refer to com.etcbase.mockito.service.MockitoExpectedTest.java in source code for complete example.
Even though void methods doesn’t return a value, behinde the scene it do return something depending on the programming language and implementation.
With Mockito we can use doAnswer() to mock a void method, doThrow() to throw an exception from a void method. The following example illustrate that.
Mockito.doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
return null;
}
}).when(etcBaseDao).delete(Mockito.any(Long.class));
refer to com.etcbase.mockito.service.MockitoVoidTest.java in the source code for complete example.
Apart from asserting that the return values are valid, we can also verify that a given method is called on a given mock object during test execution, most especially when the method under test is a Void method.
There are two types of verify methods
- One that takes the mock object only and
- The second one that takes mock object and verification mode
Mockito.verify(theService).theMethod(...);
Mockito.verify(theService, Mockito.times(1)).theMethod(...);
refer to com.etcbase.mockito.service.MockitoWithVerifyTest.java in the source code for complete example.
Verification modes
- Mockito.times(…)
- Mockito.atLeast(…)
- Mockito.atMost(…)
- Mockito.calls(…)
- Mockito.only(…)
- Mockito.atLeastOnce()
- Mockito.never()
The argument captor allows you to capture any argument that is passed into a mock method. Mockito.ArgumentCaptor
@Captor
private ArgumentCaptor<EtcBase> etcBaseArgumentCaptor;
refer to com.etcbase.mockito.service.MockitoArgumentCaptorTest.java in the source code for complete example.
It’s not alway that we want to mock everything, sometimes we do want to interact with the real service and verify that it was invoked, that is where Mockito spy is at your back.
When a dependency is annotated with @Spy Mockito will create a wrapper around the a real instance of that object so that it can be called.
@Spy // instead of using @Mock we use @Spy
private EtcBaseDao etcBaseDao;
The Mockito MockitoJUnitRunner give you automatic validation and automatic initMocks(). For example, in the case of automatic validation, Mockito might not instantly report an error when the Mockito.when() is used without then or thenReturn until when Mockito.verify() in reached.
@Test
public void successAutomaticValidation() {
// Error is here but
when(myMock.method1());
// Do something here
// Error is reported here
verify(myMock).method2();
}
Also, as mention above. Instead of using MockitoAnnotations.initMocks(this); the runner gives you automatic initMocks()
If you have any question you can send it through my email address. bellomodigimba@gmail.com