I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE COURSE

1. Overview

In this quick tutorial, we’ll look at three different ways of creating mock objects and how they differ from each other – with Mockito and with the Spring mocking support.

2. Mockito.mock()

The Mockito.mock() method allows us to create a mock object of a class or an interface.

Then, we can 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();
}

This method doesn’t need anything else to be done before it can be used. 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. As well, 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 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)

Also, 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 – for example, 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, as well as being registered in the application context, the mock will also be injected into the field.

This is evident in the code above. Here, we have used the injected UserRepository mock to stub the count method. We have then used the bean from the application context to verify that it is indeed the mocked bean.

5. Conclusion

In this article, we saw how the three methods for creating mock objects differ and how each can be used.

The source code that accompanies this article is available over on GitHub.

I just announced the new Spring Boot 2 material, coming in REST With Spring:

>> CHECK OUT THE LESSONS

newest oldest most voted
Notify of
James
Guest
James

The “more proper” ways of doing this with JUnit are:

With Junit5:

@ExtendWith(MockitoExtension.class)
public class MyTest {
….
}

With Junit4:

public class MyTest {
@Rule
public MockitoRule rule = MockitoJUnit.rule();
….
}

Loredana Crusoveanu
Editor

Sure, but the focus here was on the differences between the 3 methods.