logo
Interview
Spring Boot Testing Interview Questions
Is Spring Boot testing your second nature?
springboottesting
Question 1
What is the difference between Mockito's @Mock and Spring Boot Test's @MockBean?
@Mock
Basic vanilla Mockito annotation which allows for shorthand mock creation.

This is equivalent of Mockito.mock() method.

We can use the @InjectMocks annotation in order to inject the mocks annotation with @Mock into the SUT.


@MockBean
Having in general the same idea as the @Mock annotation, the @MockBean annotation , used within an integration test scenario, replaces the real instance of a Spring Bean with a mock in the Spring Context. Which can be later stubbed or verified as required.
Absolutely nothing. @SpringBootTests and other test annotations like @DataJpaTest by default contain the required extension:

@ExtendWith(value=org.springframework.test.context.junit.jupiter.SpringExtension.class)
@WebFluxTest annotation are used to make sure the WebFlux controllers are working as expected.

@WebFluxTest scans following beans: @Controller, @ControllerAdvice, @JsonComponent, Converter, GenericConverter, and WebFluxConfigurer.

Everything else is omitted.

Here is an example test case:

 @RunWith(SpringRunner.class)
 @WebFluxTest(UserController.class)
 public class UserControllerTests {

     @Autowired
     private WebTestClient webClient;

     @MockBean
     private UserService userService;

     @Test
     public void testExample() throws Exception {
        when(userService.getUserDetails("jimmy"))
          .thenReturn(new UserDetails("Jimmy", "Page"));

        webClient.get().uri("/users/jimmy")
        .exchange()
        .expectStatus().isOk()
        .expectBody(String.class).isEqualTo("Jimmy Page");
      }

  • To manage Spring IoC container caching between tests.
  • To provide Dependency Injection of test fixture instances.
  • To provide transaction management appropriate to integration testing.
  • To supply Spring-specific base classes that assist developers in writing integration tests.


Spring IoC container caching
Unless we are dealing with a very simple spring app, the cost of loading the ApplicationContext and WebApplicationContext instances can be quite high. We are talking 10 seconds and up. Thanks to context caching, spring recreates the application context state for each of the tests. It is loaded only once for the first test.
This enhances usability of our integration test suite greatly. Otherwise it would take ages to finish and eventually would make the suite not usable.
@Commit indicates that the transaction should be committed after the test method has completed (given it is configured as transactional).

The @Commit annotation is a direct replacement for @Rollback(false) to more explicitly convey the intent of the code.

We can declare @Commit on a class level thus making all the methods be affected by it.
@Sql is used to annotate a test class or test method to configure SQL scripts to be run against a given database during integration tests.


@Test
@Sql({"/schema-base.sql", "/user-data-populate.sql"})
public void shouldUpdateUser {
// the success of this method would relly on the initially loaded data.
}
We can define the list of property files that ought to be used in our test with the @TestPropertySource annotation:


@ContextConfiguration
@TestPropertySource({"/application-test.properties", "/auxiliary.properties"})
public class SourceIT {


In order to add additional properties ad-hoc, we use the same annotation:


@ContextConfiguration
@TestPropertySource(
    locations = "/application-test.properties",
    properties = {"file.extension = pdf", "timeout: 1000"}
)
public class SourceIT {
There is a webEnvironment property that we can set as follows:


@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SourceIT
Here we will start the actual servlet container on a random port.
This can be autowired using the @LocalServerPort.

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
public class SourceIT
Here spring will take the defined port from the properties and start the server with it.


Although slower in set-up than the mocked one, it allows to run you integration tests with as close to production scenario as possible.
The request is sent over a TCP connection which then hits a running servlet container.
Given a mocked environment we are hitting the DispatcherServlet straight away.
JdbcTestUtils is a collection of JDBC related utility functions intended to simplify standard database testing scenarios.

  • countRowsInTable
  • countRowsInTableWhere
  • deleteFromTables
  • deleteFromTableWhere
  • dropTables
By using @ContextConfiguration:

@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = {TestAppConfig.class, TestAppConfig2.class})
public class SourceIT {


By using @Configuration straight in the test class:

@RunWith(SpringRunner.class)
@SpringBootTest
public class SourceIT {

  @Configuration
  static class TestContextConfiguration {
    @Bean
    @Primary
    public MyBean myBean () {
      return new myBean();
    }
  }