Creating Mocks With Mockito
After we have finished this lesson, we:
- Understand how we should create our mock objects.
- Can verify interactions that happened between the system under test and a mock object.
- Know how we can capture the actual method parameter of an invoked method.
This lesson assumes that:
Creating Mocks With Mockito
As we remember, we can create a dummy, a stub, or a mock by invoking the mock() method of the Mockito class.
Also, because the test doubles created with Mockito are not stateless, we have to create our test doubles before a test method is invoked. This means that we have to create them in a setup method that is annotated with the @Before annotation.
However, this time we don’t have to add any methods into the TestDoubles class because it is crystal clear that the mock() method creates a mock object.
After we have created our mock object in a setup method, the source code of our test class looks as follows:
1import org.junit.Before;
2
3import static org.mockito.Mockito.mock;
4
5public class MockitoTest {
6
7 private TaskRepository repository;
8
9 @Before
10 public void createMock() {
11 repository = mock(TaskRepository.class);
12 }
13}
The system under test was described in the lesson: Creating Stubs With Mockito
. Also, I have removed the unused methods from the TaskRepository interface because they were not relevant for this lesson.
Also, if you want to use Strict mocks, you should add a new factory method called strictMock() into the TestDoubles class and use that method instead of the mock() method. This approach has two benefits:
- It helps you to reduce duplicate code because you don’t have to override the default answer every time when you create a new strict mock.
- It helps you to clarify your intentions and reduce misunderstandings.
After you have added this method into the TestDoubles class, its source code looks as follows:
1import org.mockito.invocation.InvocationOnMock;
2import org.mockito.stubbing.Answer;
3
4import static org.mockito.Mockito.mock;
5
6public final class TestDoubles {
7
8 private TestDoubles() {}
9
10 public static <T> T dummy(Class<T> dummyClass) {
11 return mock(dummyClass);
12 }
13
14 public static <T> T strictStub(Class<T> stubClass) {
15 return mock(stubClass, new Answer() {
16 @Override
17 public Object answer(InvocationOnMock i) throws Throwable {
18 throw new RuntimeException(
19 "SUT invoked an unexpected method of a stub"
20 );
21 }
22 });
23 }
24
25 public static <T> T stub(Class<T> stubClass) {
26 return mock(stubClass);
27 }
28
29 public static <T> T strictMock(Class<T> mockClass) {
30 return mock(mockClass, new Answer() {
31 @Override
32 public Object answer(InvocationOnMock i) throws Throwable {
33 throw new RuntimeException(
34 "SUT invoked an unexpected method of a mock"
35 );
36 }
37 });
38 }
39}
Let’s find out how we can verify interactions with Mockito.
Verifying Interactions With Mockito
The Mockito class provides three static methods which we can use for verifying interactions that happened between the system under test and our mock object. These methods are:
- The
verify()method verifies that a specific interaction happened between the system under test and our mock object. TheMockitoclass has twoverify()methods which are used for different purposes and both of these methods return a reference to the verified mock object. - The
verifyNoMoreInteractions()method fails the test if any of the mock objects given as method parameters has unverified interactions. In other words, this method checks if the mock objects have interactions that were not verified by invoking theverify()method. Even though this method can be useful in certain situations, we should not use this method in every test method. - The
verifyZeroInteractions()method verifies that no interactions happened between the system under test and the mock objects given as method parameters.
Additional Reading:
Next we will find out how we can use these methods in our unit tests.
Verifying Method Invocations
The next five examples demonstrate how we can verify interactions that happened or did not happen between the system under test and our mock object.
Example 1: Method Was Invoked Once
If we want to verify that the system under test invoked a method of our mock object only one time, we have to follow these steps:
- Configure the verified mock by by invoking the
verify()method of theMockitoclass. When we invoke this method, we have to pass a mock object as a method parameter. - Configure the invoked method by invoking it. If the invoked method has method parameters, we have to configure the expected method parameters when we configure the invoked method.
If we want to verify that the findById() method of the TaskRepository interface was invoked once and 1L was passed as a method parameter, we have to write a unit test that looks as follows:
1import org.junit.Before;
2import org.junit.Test;
3
4import static org.mockito.Mockito.mock;
5import static org.mockito.Mockito.verify;
6
7public class MockitoTest {
8
9 private TaskRepository repository;
10
11 @Before
12 public void createMock() {
13 repository = mock(TaskRepository.class);
14 }
15
16 @Test
17 public void verifyWhenMethodWasCalledOnce() {
18 repository.findById(1L);
19
20 verify(repository).findById(1L);
21 }
22}
Example 2: Method Was Invoked X Times
If we want to verify that the system under test invoked a method of our mock object X times, we have to follow these steps:
- Invoke the
verify()method of theMockitoclass and pass the following objects as method parameters: - The target mock object.
- A
VerificationModeobject that specifies how many times the method must be invoked by the system under test. - Configure the invoked method by invoking it. If the invoked method has method parameters, we have to configure the expected method parameters when we configure the invoked method.
If we want to verify that the findById() method of the TaskRepository interface was invoked once and 1L was passed as a method parameter, we have to create the second method parameter by invoking the times() method of the Mockito class. When we invoke this method, we have to pass the number of expected method invocations (1) as a method parameter.
After we have written our unit test, its source code looks as follows:
1import org.junit.Before;
2import org.junit.Test;
3
4import static org.mockito.Mockito.mock;
5import static org.mockito.Mockito.times;
6import static org.mockito.Mockito.verify;
7
8public class MockitoTest {
9
10 private TaskRepository repository;
11
12 @Before
13 public void createMock() {
14 repository = mock(TaskRepository.class);
15 }
16
17 @Test
18 public void verifyThatMethodWasCalledOnce() {
19 repository.findById(1L);
20
21 verify(repository, times(1)).findById(1L);
22 }
23}
The Mockito class provides a few other factory methods that can be used for creating new VerificationMode objects. The Mockito API documentation provides more information about these factory methods.
Additional Reading:
Example 3: Method Was Never Invoked
If we want to verify that a method of our mock object was not invoked by the system under test, we have to create the second method parameter that is passed to the verify() method of the Mockito class by invoking the never() method of the Mockito class.
If we want to ensure that the findById() method of the TaskRepository interface was never invoked by using the method parameter 1L, we have to write a unit test that looks as follows:
1import org.junit.Before;
2import org.junit.Test;
3
4import static org.mockito.Mockito.mock;
5import static org.mockito.Mockito.never;
6import static org.mockito.Mockito.verify;
7
8public class MockitoTest {
9
10 private TaskRepository repository;
11
12 @Before
13 public void createMock() {
14 repository = mock(TaskRepository.class);
15 }
16
17 @Test
18 public void verifyThatMethodWasNotInvoked() {
19 verify(repository, never()).findById(1L);
20 }
21}
Example 4: There Are No Unverified Interactions
If we want to verify that our mock has no unverified interactions, we have to follow these steps:
- Specify the expected interactions.
- Invoke the
verifyNoMoreInteractions()method of theMockitoclass and pass theTaskRepositorymock as a method parameter.
For example, if we want to verify that the system under test invoked the findById() method once by using the method parameter 1L and it didn’t invoke any other methods of the TaskRepository interface, we have to write a unit test that looks as follows:
1import org.junit.Before;
2import org.junit.Test;
3
4import static org.mockito.Mockito.mock;
5import static org.mockito.Mockito.verify;
6import static org.mockito.Mockito.verifyNoMoreInteractions;
7
8public class MockitoTest {
9
10 private TaskRepository repository;
11
12 @Before
13 public void createMock() {
14 repository = mock(TaskRepository.class);
15 }
16
17 @Test
18 public void verifyThatNoOtherMethodsWereInvoked() {
19 repository.findById(1L);
20
21 verify(repository).findById(1L);
22 verifyNoMoreInteractions(repository);
23 }
24}
Example 5: There Were No Interactions Between the System Under Test and Our Mock
If we want to verify that the system under test did not invoke any methods of the TaskRepository interface, we have to invoke the verifyZeroInteractions() method of the Mockito class and pass the TaskRepository mock object as a method parameter.
After we have written our unit test, its source code looks as follows:
1import org.junit.Before;
2import org.junit.Test;
3
4import static org.mockito.Mockito.mock;
5import static org.mockito.Mockito.verifyZeroInteractions;
6
7public class MockitoTest {
8
9 private TaskRepository repository;
10
11 @Before
12 public void createMock() {
13 repository = mock(TaskRepository.class);
14 }
15
16 @Test
17 public void verifyThatNoInteractionsHappenedBetweenSUTAndMock() {
18 verifyZeroInteractions(repository);
19 }
20}
Using Argument Matchers
As we remember, If we configure the expected method parameter of an invoked method by simply passing it to the invoked method, Mockito verifies it by using the equals() method. Even though this is fine for most situations, sometimes we need extra flexibility. When this happens, we can specify the expected method parameter by using an argument matcher that is passed to the invoked method as a method parameter.
The org.mockito.Matchers class provides factory methods that we can use for creating different argument matchers. Let’s take a look at two examples that demonstrate how argument matchers work.
First, if we want to ensure that the findById() method of the TaskRepository interface was invoked by using a method parameter that is equal to 1L, we have to create our argument matcher by using the eq() method of the Matchers class.
After we have configured the expected method parameter by using the created argument matcher, the source code of our test method looks as follows:
1import org.junit.Before;
2import org.junit.Test;
3
4import static org.mockito.Matchers.eq;
5import static org.mockito.Mockito.mock;
6import static org.mockito.Mockito.verify;
7
8public class MockitoTest {
9
10 private TaskRepository repository;
11
12 @Before
13 public void createMock() {
14 repository = mock(TaskRepository.class);
15 }
16
17 @Test
18 public void verifyThatMethodWasInvokedByPassing1LAsMethodParameter() {
19 repository.findById(1L);
20
21 verify(repository).findById(eq(1L));
22 }
23}
Second, if we want to verify that the findById() method of the TaskRepository interface was invoked and a Long object was passed as a method parameter, we have to create our argument matcher by using the anyLong() method of the Matchers class.
After we have configured the expected method parameter by using the created argument matcher, the source code of our test method looks as follows:
1import org.junit.Before;
2import org.junit.Test;
3
4import static org.mockito.Matchers.anyLong;
5import static org.mockito.Mockito.mock;
6import static org.mockito.Mockito.verify;
7
8public class MockitoTest {
9
10 private TaskRepository repository;
11
12 @Before
13 public void createMock() {
14 repository = mock(TaskRepository.class);
15 }
16
17 @Test
18 public void verifyThatMethodWasInvokedByPassingAnyLongAsMethodParameter() {
19 repository.findById(1L);
20
21 verify(repository).findById(anyLong());
22 }
23}
Additional Reading:
Using an Argument Captor
If we want to write assertions for the actual method parameter, we cannot use the “standard” argument matchers provided by the Matchers class because we have to capture the actual method parameter before we can write assertions for it. We can capture the actual method parameter by using the ArgumentCaptor<T> class.
For example, if we want to verify that the actual method pararameter that was passed to the findById() method of the TaskRepository interface is equal to 1L, we have to follow these steps:
- Create an
ArgumentCaptor<Long>object by invoking thestaticforClass()method of theArgumentCaptorclass. When we invoke this method, we have to pass aClassobject that specifies the type of the captured parameter (Long.class) as a method parameter. - Ensure that the
findById()method of theTaskRepositoryinterface was invoked once and configure the expected method parameter by invoking thecapture()method of theArgumentCaptorclass. - Get the actual method parameter by invoking the
getValue()method of theArgumentCaptorclass. - Ensure that the actual method parameter is equal to
1L
After we have finished these steps, the source code of our test method looks as follows:
1import org.junit.Before;
2import org.junit.Test;
3import org.mockito.ArgumentCaptor;
4
5import static org.assertj.core.api.Assertions.assertThat;
6import static org.mockito.Mockito.mock;
7import static org.mockito.Mockito.verify;
8
9public class MockitoTest {
10
11 private TaskRepository repository;
12
13 @Before
14 public void createMock() {
15 repository = mock(TaskRepository.class);
16 }
17
18 @Test
19 public void verifyThatMethodWasInvokedByUsingArgumentCaptor() {
20 repository.findById(1L);
21
22 ArgumentCaptor<Long> argument = ArgumentCaptor.forClass(Long.class);
23 verify(repository).findById(argument.capture());
24
25 Long actualId = argument.getValue();
26 assertThat(actualId).isEqualByComparingTo(1L);
27 }
28}
Additional Reading:
We can now verify interactions that happened between the system under test and our mock object. Let’s put our new skills into practice.
Putting Theory Into Practice
Let’s use our new skills and write one unit test for the createCopyOf() method of the TaskService class. We have to write a unit test which ensures that the saved Task object contains the correct information.
Also, because the goal of this lesson is to teach us how we can verify interactions with Mockito, the other parts of this unit test have been implemented by unknown developer.
createCopyOf() method of the TaskService class was described in the lesson: Creating Stubs With Mockito
.
We can write our unit test by following these steps:
- Create a new
ArgumentCaptor<Task>object. - Ensure that the
save()method of theTaskRepositoryinterface was invoked once and capture the actual method parameter. - Get the actual method parameter.
- Verify that the saved
Taskobject contains the correct information.
After we have finished our unit test, the source code of our test method looks as follows:
1import org.junit.Before;
2import org.junit.Test;
3import org.mockito.ArgumentCaptor;
4import org.mockito.invocation.InvocationOnMock;
5
6import java.util.Optional;
7
8import static org.assertj.core.api.Assertions.assertThat;
9import static org.mockito.BDDMockito.given;
10import static org.mockito.Matchers.isA;
11import static org.mockito.Mockito.mock;
12import static org.mockito.Mockito.verify;
13
14public class MockitoTaskServiceTest {
15
16 private final Long CREATOR_ID = 33L;
17 private final String CREATOR_USERNAME = "username";
18 private final Long SOURCE_TASK_ID = 99L;
19 private final String SOURCE_TASK_DESCRIPTION = "description";
20 private final String SOURCE_TASK_TITLE = "title";
21
22 private TaskRepository repository;
23 private TaskService service;
24
25 @Before
26 public void configureSystemUnderTest() {
27 repository = mock(TaskRepository.class);
28 service = new TaskService(repository);
29 }
30
31 @Test
32 public void createCopyOf_WhenSourceTaskIsFound_ShouldSaveNewTask() {
33 Task sourceTask = new TaskBuilder()
34 .withDescription(SOURCE_TASK_DESCRIPTION)
35 .withTitle(SOURCE_TASK_TITLE)
36 .build();
37
38 given(repository.findById(SOURCE_TASK_ID))
39 .willReturn(Optional.of(sourceTask));
40
41 LoggedInUser creator = new LoggedInUser(CREATOR_ID, CREATOR_USERNAME);
42 service.createCopyOf(SOURCE_TASK_ID, creator);
43
44 ArgumentCaptor<Task> taskArgument = ArgumentCaptor.forClass(Task.class);
45 verify(repository).save(taskArgument.capture());
46
47 Task created = taskArgument.getValue();
48 assertThat(created.getCreator().getUserId())
49 .isEqualByComparingTo(CREATOR_ID);
50 assertThat(created.getDescription())
51 .isEqualTo(SOURCE_TASK_DESCRIPTION);
52 assertThat(created.getTitle()).isEqualTo(SOURCE_TASK_TITLE);
53 }
54}
Let’s summarize what we learned from this lesson.
Summary
This lesson has taught us six things:
- We have to create our mock object before a test method is invoked.
- We should create our mock object by using the
mock()method of theMockitoclass. - We can verify interactions that happened between the system under test and a mock object by using the methods provided by the
Mockitoclass. - By default, Mockito compares the expected method parameter with the actual method parameter by using the
equals()method. - We can customize the method parameter verification process by using argument matchers.
- If we need to get a reference to the actual method parameter, we have to use an argument captor.