How does Spring Boot support integration testing?
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.
@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.
@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@DataJpaTestbut for plain JDBC repositories.@WebFluxTest: For testing Spring WebFlux controllers.@RestClientTest: For testing REST clients by auto-configuringRestTemplateBuilderorWebClient.Builderand a mock server.
@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.