🌱 Spring Boot Q41 / 69

How does Spring Boot support integration testing?

AI-Powered Answer ✓ Answered

Spring Boot provides a robust and convenient framework for integration testing, enabling developers to test their applications with a full Spring context or a subset thereof. It simplifies the setup and teardown of test environments, allowing for comprehensive validation of component interactions and external service integrations.

The @SpringBootTest Annotation

The primary annotation for Spring Boot integration tests is @SpringBootTest. When applied to a test class, it tells Spring Boot to create an ApplicationContext that is very similar to the one used by the actual application. This means it will load all components, configurations, and auto-configurations, making it ideal for testing the entire application stack. By default, it uses a mock web environment, but it can be configured to run with a real or random port.

java
@RunWith(SpringRunner.class)
@SpringBootTest(
    webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
    properties = "spring.profiles.active=test"
)
public class MyServiceIntegrationTest {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void contextLoads() {
        // Application context loaded successfully
    }

    @Test
    public void testEndpoint() {
        String body = this.restTemplate.getForObject("/api/hello", String.class);
        assertThat(body).isEqualTo("Hello, World!");
    }
}

Mocking and Spying Beans

For tests where you want to isolate a specific part of your application from its dependencies, Spring Boot offers @MockBean and @SpyBean. @MockBean replaces an existing bean in the application context with a Mockito mock, allowing you to control its behavior and verify interactions. @SpyBean wraps an existing bean with a Mockito spy, letting you call real methods while still being able to verify or stub specific behaviors.

java
@SpringBootTest
public class OrderServiceTest {

    @MockBean
    private PaymentGatewayService paymentGatewayService; // Replaces real bean with mock

    @Autowired
    private OrderService orderService;

    @Test
    public void testPlaceOrder() {
        when(paymentGatewayService.processPayment(anyDouble())).thenReturn(true);
        boolean result = orderService.placeOrder(100.0);
        assertTrue(result);
        verify(paymentGatewayService, times(1)).processPayment(100.0);
    }
}

Test Slices for Focused Testing

Spring Boot provides specialized annotations, known as 'test slices', to load only a subset of the application context relevant to a particular layer of the application. This makes tests faster and more focused:

  • @WebMvcTest: For testing Spring MVC controllers. It auto-configures Spring MVC infrastructure but excludes other components like services or repositories.
  • @DataJpaTest: For testing JPA repositories. It configures an embedded in-memory database and auto-configures Spring Data JPA components.
  • @JdbcTest: Similar to @DataJpaTest but for plain JDBC repositories.
  • @WebFluxTest: For testing Spring WebFlux controllers.
  • @RestClientTest: For testing REST clients by auto-configuring RestTemplateBuilder or WebClient.Builder and a mock server.
java
@WebMvcTest(UserController.class)
public class UserControllerWebMvcTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserService userService;

    @Test
    public void testGetUserById() throws Exception {
        when(userService.findById(1L)).thenReturn(new User(1L, "John Doe"));

        mockMvc.perform(get("/users/1"))
               .andExpect(status().isOk())
               .andExpect(jsonPath("$.name").value("John Doe"));
    }
}

Embedded Databases and Testcontainers

For database-related integration tests, Spring Boot excels. It can easily configure in-memory databases like H2 or HSQLDB for fast, isolated tests. For more realistic integration with external services or databases, Spring Boot integrates seamlessly with Testcontainers, allowing you to spin up Docker containers for databases (e.g., PostgreSQL, MySQL), message brokers (e.g., Kafka), or other services as part of your test lifecycle.

Active Profiles and Properties

You can use @ActiveProfiles to activate specific Spring profiles for your integration tests, allowing different configurations (e.g., a 'test' profile with specific database settings or mock service URLs). Additionally, the properties attribute in @SpringBootTest or @TestPropertySource can be used to override application properties directly within the test.

Auto-configuration Exclusions

For fine-grained control, Spring Boot allows you to exclude specific auto-configurations from being applied during tests. This can be done using the exclude attribute on @SpringBootTest or @EnableAutoConfiguration if you want to prevent certain beans or infrastructure from loading, further optimizing test performance and scope.