Spring boot @MockBean annotation used to add mocks to a Spring ApplicationContext
. In this tutorial, we will learn the different ways to use this annotation.
1. @MockBean annotation
- It allow to mock a class or an interface and to record and verify behaviors on it.
- It can be used as a class level annotation or on fields in either
@Configuration
classes, or test classes that are@RunWith
the SpringRunner.@RunWith(SpringRunner.class) public class ApiControllerTest { @MockBean private ApiService service; }
@RunWith(SpringRunner.class) @MockBean(ApiService.class) public class ApiControllerTest { @Autowired private ApiService service; }
@RunWith(SpringRunner.class) public class ApiControllerTest { @Autowired private ApiService service; @Configuration @Import(AppConfiguration.class) static class Config { @MockBean private ApiService service; } }
- Any existing single bean of the same type defined in the context will be replaced by the mock. If no existing bean is defined a new one will be added.
- Mocks can be registered by type or by bean name.
- If there is more than one bean of the requested type, @Qualifier metadata must be specified at field level.
@MockBean @Qualifier("apiV1") private ApiService service;
- When @MockBean is used on a field, as well as being registered in the application context, the mock will also be injected into the field.
- This annotation is
@Repeatable
and may be specified multiple times when working with Java 8 or contained within an @MockBeans annotation.@MockBeans({ @MockBean(EmployeeService.class), @MockBean(EmployeeRepository.class) }) public class EmployeeControllerTest { @Autowired EmployeeService service; @Autowired EmployeeRepository repository; }
- @MockBean is similar to mockito’s @Mock but with Spring support.
2. Mockito’s @Mock vs Spring boot’s @MockBean
Both annotations are used to add mock objects which allow to mock a class or an interface and to record and verify behaviors on it. However, we can prefer to use one over another in a certain way.
As we write a test that doesn’t need any dependencies from the Spring Boot container, the Mockito‘s @Mock
shall be used. It is fast and favors the isolation of the tested component.
If the test needs to rely on the Spring Boot container and we want also to add or mock one of the container beans then @MockBean
from Spring Boot is preferred way to add mocks.
3. @MockBean in unit testing
We will generally use @MockBean
along with either @WebMvcTest or @WebFluxTest annotations. These annotations are for web test slice and limited to a single controller.
we can use @MockBean to provide mock implementations for required collaborators in the controller class.
4. @MockBean Example
We have already seen the usage of @MockBean in @WebFluxTest example.
In given test class, we are testing the REST endpoints of flux controller class EmployeeController
. It tests the api methods and service interaction – while it mocks the persistence layer code (i.e. EmployeeRepository).
@ExtendWith(SpringExtension.class) @WebFluxTest(controllers = EmployeeController.class) @Import(EmployeeService.class) public class EmployeeControllerTest { @MockBean EmployeeRepository repository; @Autowired private WebTestClient webClient; @Test void testCreateEmployee() { Employee employee = new Employee(); employee.setId(1); employee.setName("Test"); employee.setSalary(1000); Mockito.when(repository.save(employee)).thenReturn(Mono.just(employee)); webClient.post() .uri("/create") .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromObject(employee)) .exchange() .expectStatus().isCreated(); Mockito.verify(repository, times(1)).save(employee); } }
Drop me your questions in comments.
Happy Learning !!
guess you need @ with MockBean
Thanks for pointing out this typo. Corrected.
@MockBean Resttemplate is ujsing mocked instance only for the first time it is used…the second time it is not using the mocked RestTemplate…is this behaviour expected?
Yes. But i wanted to test the Json part. If possible can you explain in brief.