Mockito Tutorial (A comprehensive guide with examples)
Mockito is a mocking framework for Java which is extremely easy to use, so this post will discuss all the cool features you need to know about mockito with simple and easy examples.
- How to inject mocks
- How to mock methods with Mockito
- How to mock void methods with Mockito
- 2 Ways to test void methods with Mockito
- Spying with Mockito
WHY MOCK?
Most of the classes we come across have dependencies. and often times methods delegates some of the work to other methods in other classes, and we call these classes dependencies. When unit testing such methods, if we only used JUnit, our tests will also depend on those methods as well. We want the unit tests to be independent of all other dependencies.
- eg: we want to test the method
addCustomer
inCustomerService
class, and within thisaddCustomer
method, the save method of theCustomerDao
class is invoked. We don’t want to call the real implementation of theCustomerDao
save()
method for a few reasons:- We only want to test the logic inside the
addCustomer()
in isolation. - We may not yet have implemented it.
- We don’t want the unit test of the
addCustomer()
fail if there is a defect insave()
method in theCustomerDao
.
- We only want to test the logic inside the
- So we should some how mock the behavior of the dependencies. This is where mocking frameworks comes in to play.
- Mockito framework is what I use for just this and in this post we’ll see how to use mockito effectively to mock those dependencies.
If you are new to unit testing with JUnit, please check out the previous post on How to write great unit tests with JUnit
What is mockito?
Mockito is a mocking framework that tastes really good. It lets you write beautiful tests with a clean & simple API. Mockito doesn’t give you hangover because the tests are very readable and they produce clean verification errors.
— “Mockito.” Mockito Framework Site. N.p., n.d. Web. 28 Apr. 2017.
HOW TO INJECT MOCKS
So going back to the example above, how do we mock out the dependency using Mockito? Well, we could inject a mock to the class under test instead of the real implementation while we run our tests!
Let’s look at an example of a class under test which has a dependency on CustomerDao
public class CustomerService {
@Inject
private CustomerDao customerDao;
public boolean addCustomer(Customer customer){
if(customerDao.exists(customer.getPhone())){
return false;
}
return customerDao.save(customer);
}
public CustomerDao getCustomerDao() {
return customerDao;
}
public void setCustomerDao(CustomerDao customerDao) {
this.customerDao = customerDao;
}
}
Following is the test which mocks the dependency using Mockito
public class CustomerServiceTest {
@Mock
private CustomerDao daoMock;
@InjectMocks
private CustomerService service;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void test() {
//assertion here
}
}
Let’s look at the role of the annotations in the above example.
@Mock
will create a mock implementation for theCustomerDao
@InjectMocks
will inject the mocks marked with@Mock
to this instance when it is created.- So when or where are these instances created? Well, it is done by this line which reside in the setUp method.
MockitoAnnotations.initMocks(this);
- So these instances would be created at the start of every test method of this test class.
HOW TO MOCK METHODS WITH MOCKITO
Great! now we have successfully created and injected the mock, and now we should tell the mock how to behave when certain methods are called on it.
The when
then
pattern
- We do this in each of the test methods, the following line of code tells the Mockito framework that we want the
save()
method of the mock dao instance to return true when passed in a certain customer instance.
when(dao.save(customer)).thenReturn(true);
when
is a static method of the Mockito class and it returns anOngoingStubbing<T>
(T
is the return type of the method that we are mocking, in this case it isboolean
)- So if we just extract that out to get hold of the stub, it looks like this:
OngoingStubbing<Boolean> stub = when(dao.save(customer));
- Following are some of the methods that we can call on this
stub
thenReturn(returnValue)
thenThrow(exception)
thenCallRealMethod()
thenAnswer()
- this could be used to set up smarter stubs and also mock behavior of void methods as well (see How to mock void method behavior).
-
Simply putting this all in one line again.
when(dao.save(customer)).thenReturn(true);
-
Do we really need to pass in an actual customer object to the save method here? No, we could use matchers like the following:
when(dao.save(any(Customer.class))).thenReturn(true);
-
However, when there are multiple parameters to a method, we cannot mix matchers and actual objects, for example we cannot do the following:
Mockito.when(mapper.map(any(), "test")).thenReturn(new Something());
This would compile without a complaint but would fail during runtime with an error saying:
matchers can't be mixed with actual values in the list of arguments to a single method.
- We either have to use matchers for all parameters or should pass in real values or objects.
Mock behavior of dependencies using Mockito.when
- Example
package com.tdd;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class CustomerServiceTest {
@Mock
private CustomerDao daoMock;
@InjectMocks
private CustomerService service;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void testAddCustomer_returnsNewCustomer() {
when(daoMock.save(any(Customer.class))).thenReturn(new Customer());
Customer customer = new Customer();
assertThat(service.addCustomer(customer), is(notNullValue()));
}
//Using Answer to set an id to the customer which is passed in as a parameter to the mock method.
@Test
public void testAddCustomer_returnsNewCustomerWithId() {
when(daoMock.save(any(Customer.class))).thenAnswer(new Answer<Customer>() {
@Override
public Customer answer(InvocationOnMock invocation) throws Throwable {
Object[] arguments = invocation.getArguments();
if (arguments != null && arguments.length > 0 && arguments[0] != null){
Customer customer = (Customer) arguments[0];
customer.setId(1);
return customer;
}
return null;
}
});
Customer customer = new Customer();
assertThat(service.addCustomer(customer), is(notNullValue()));
}
//Throwing an exception from the mocked method
@Test(expected = RuntimeException.class)
public void testAddCustomer_throwsException() {
when(daoMock.save(any(Customer.class))).thenThrow(RuntimeException.class);
Customer customer = new Customer();
service.addCustomer(customer);//
}
}
HOW TO MOCK VOID METHOS WITH MOCKITO
doAnswer
- If we want our mocked void method to do something (mock the behavior despite being void).doThrow
- Then there isMockito.doThrow()
if you want to throw an exception from the mocked void method.
Following is an example of how to use it (not an ideal usecase but just wanted to illustrate the basic usage).
@Test
public void testUpdate() {
doAnswer(new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
Object[] arguments = invocation.getArguments();
if (arguments != null && arguments.length > 1 && arguments[0] != null && arguments[1] != null) {
Customer customer = (Customer) arguments[0];
String email = (String) arguments[1];
customer.setEmail(email);
}
return null;
}
}).when(daoMock).updateEmail(any(Customer.class), any(String.class));
// calling the method under test
Customer customer = service.changeEmail("[email protected]", "[email protected]");
//some asserts
assertThat(customer, is(notNullValue()));
assertThat(customer.getEmail(), is(equalTo("[email protected]")));
}
@Test(expected = RuntimeException.class)
public void testUpdate_throwsException() {
doThrow(RuntimeException.class).when(daoMock).updateEmail(any(Customer.class), any(String.class));
// calling the method under test
Customer customer = service.changeEmail("[email protected]", "[email protected]");
}
}
HOW TO TEST VOID METHODS WITH MOCKITO - TWO WAYS
Methods with return values can be tested by asserting the returned value, but how to test void methods? The void method that you want to test could either be calling other methods to get things done or processing the input parameters or maybe generating some values or all of it. With Mockito, you can test all of the above scenarios.
1 | Verify with Mockito
- A great thing about mocking is that we can verify that certain methods have been called on those mock objects during test execution in addition to assertions or in place of assertions when the method under test is void.
- There are two overloaded verify methods.
- one which accepts only the mock object - we can use this if the method is supposed to be invoked only once.
- the other accepts the mock and a
VerificationMode
- there are quite a few methods in the Mockito class which provides some useful verificationModestimes(int wantedNumberOfInvocations)
atLeast( int wantedNumberOfInvocations )
atMost( int wantedNumberOfInvocations )
calls( int wantedNumberOfInvocations )
only( int wantedNumberOfInvocations )
atLeastOnce()
never()
Mockito.verify
- Example
package com.tdd;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class CustomerServiceTest {
@Mock
private CustomerDao daoMock;
@InjectMocks
private CustomerService service;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void test() {
when(daoMock.save(any(Customer.class))).thenReturn(true);
Customer customer=new Customer();
assertThat(service.addCustomer(customer), is(true));
//verify that the save method has been invoked
verify(daoMock).save(any(Customer.class));
//the above is similar to : verify(daoMock, times(1)).save(any(Customer.class));
//verify that the exists method is invoked one time
verify(daoMock, times(1)).exists(anyString());
//verify that the delete method has never been invoked
verify(daoMock, never()).delete(any(Customer.class));
}
}
2 | Capture Arguments
Another cool feature is the ArgumentCaptor
which allows us to capture any arguments passed in to the mocked or spied methods.
Mockito.ArgumentCaptor
- Example
package com.service;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.verify;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import com.dao.CustomerDao;
import com.entity.Customer;
public class CustomerServiceTest {
@Mock
private CustomerDao doaMock;
@InjectMocks
private CustomerService service;
@Captor
private ArgumentCaptor<Customer> customerArgument;
public CustomerServiceTest() {
MockitoAnnotations.initMocks(this);
}
@Test
public void testRegister() {
//Requirement: we want to register a new customer. Every new customer should be assigned a random token before saving in the database.
service.register(new Customer());
//captures the argument which was passed in to save method.
verify(doaMock).save(customerArgument.capture());
//make sure a token is assigned by the register method before saving.
assertThat(customerArgument.getValue().getToken(), is(notNullValue()));
}
}
HOW TO SPY WITH MOCKITO
Why spy?
- Sometimes we do need to call real methods of a dependency but still want to verify or track interactions with that dependency, this is where we would use a spy.
- When a field is annotated with
@Spy
, Mockito will create a wrapper around an actual instance of that object and therefore we can call real implementation and also verify interactions at the same time. - Some of the behavior of a spy could be mocked if neened.
- in the example below, the dependency behavior is not mocked but still it’s interactions are verified.
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.*;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
public class CustomerServiceTestV2 {
@Spy
private CustomerDaoImpl daoSpy;
@InjectMocks
private CustomerService service;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void test() {
Customer customer = new Customer();
assertThat(service.addCustomer(customer), is(false));
verify(daoSpy).save(any(Customer.class));
verify(daoSpy, times(1)).exists(anyString());
verify(daoSpy, never()).delete(any(Customer.class));
}
}
Click Here to get the example source code given in this tutorial.
That’s it on this post, please check out the below websites for more cool features, best practices and guidelines on Mockito.
Mockito Main reference documentation