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. Spring @MockBean Annotation
- It allows us to mock a class or an interface and record & verify its behaviors.
- It can be used on the class-level 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;
}
}
- The mock will replace any existing single bean of the same type defined in the context. 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 the field level.
@MockBean
@Qualifier("apiV1")
private ApiService service;
- The mock will also be injected into the field when @MockBean is used on a field and registered in the application context.
- 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. Difference between Mockito @Mock and Spring Boot @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 slices and are 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 the given test class, we are testing the REST endpoints of the 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 the comments.
Happy Learning !!
Leave a Reply