1. Overview
In this quick tutorial, we'll look at three different ways of creating mock objects with Mockito and with the Spring mocking support. We'll also discuss how they differ from each other.
Learn how to use the ArgumentMatcher and how it differs from the ArgumentCaptor.
Learn to configure a method call to throw an exception in Mockito.
2. Mockito.mock()
The Mockito.mock() method allows us to create a mock object of a class or an interface.
We can then use the mock to stub return values for its methods and verify if they were called.
Let's look at an example:
@Test
public void givenCountMethodMocked_WhenCountInvoked_ThenMockedValueReturned() {
UserRepository localMockRepository = Mockito.mock(UserRepository.class);
Mockito.when(localMockRepository.count()).thenReturn(111L);
long userCount = localMockRepository.count();
Assert.assertEquals(111L, userCount);
Mockito.verify(localMockRepository).count();
}
We don't need to do anything else to this method before we can use it. We can use it to create mock class fields, as well as local mocks in a method.
3. Mockito's @Mock Annotation
This annotation is a shorthand for the Mockito.mock() method. It's important to note that we should only use it in a test class. Unlike the mock() method, we need to enable Mockito annotations to use this annotation.
We can do this either by using the MockitoJUnitRunner to run the test, or by calling the MockitoAnnotations.initMocks() method explicitly.
Let's look at an example using MockitoJUnitRunner:
@RunWith(MockitoJUnitRunner.class)
public class MockAnnotationUnitTest {
@Mock
UserRepository mockRepository;
@Test
public void givenCountMethodMocked_WhenCountInvoked_ThenMockValueReturned() {
Mockito.when(mockRepository.count()).thenReturn(123L);
long userCount = mockRepository.count();
Assert.assertEquals(123L, userCount);
Mockito.verify(mockRepository).count();
}
}
Apart from making the code more readable, @Mock makes it easier to find the problem mock in case of a failure, as the name of the field appears in the failure message:
Wanted but not invoked:
mockRepository.count();
-> at org.baeldung.MockAnnotationTest.testMockAnnotation(MockAnnotationTest.java:22)
Actually, there were zero interactions with this mock.
at org.baeldung.MockAnnotationTest.testMockAnnotation(MockAnnotationTest.java:22)
Furthermore, when used in conjunction with @InjectMocks, it can reduce the amount of setup code significantly.
4. Spring Boot's @MockBean Annotation
We can use the @MockBean to add mock objects to the Spring application context. The mock will replace any existing bean of the same type in the application context.
If no bean of the same type is defined, a new one will be added. This annotation is useful in integration tests where a particular bean, like an external service, needs to be mocked.
To use this annotation, we have to use SpringRunner to run the test:
@RunWith(SpringRunner.class)
public class MockBeanAnnotationIntegrationTest {
@MockBean
UserRepository mockRepository;
@Autowired
ApplicationContext context;
@Test
public void givenCountMethodMocked_WhenCountInvoked_ThenMockValueReturned() {
Mockito.when(mockRepository.count()).thenReturn(123L);
UserRepository userRepoFromContext = context.getBean(UserRepository.class);
long userCount = userRepoFromContext.count();
Assert.assertEquals(123L, userCount);
Mockito.verify(mockRepository).count();
}
}
When we use the annotation on a field, the mock will be injected into the field, as well as being registered in the application context.
This is evident in the code above. Here we used the injected UserRepository mock to stub the count method. Then we used the bean from the application context to verify that it is indeed the mocked bean.
5. Conclusion
In this article, we examined how the three methods for creating mock objects differ, and how we can use each of them.
The source code that accompanies this article is available over on GitHub.
Course – LS (cat=Spring)
Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:
>> THE COURSE
res – Junit (guide) (cat=Testing)