@SpringBootTest
Intermediate@SpringBootTest loads the full application context for integration tests; use webEnvironment=RANDOM_PORT for tests that exercise the real HTTP stack.
Overview
@SpringBootTest is the annotation for Spring Boot integration tests. It bootstraps the full ApplicationContext — all beans, auto-configuration, embedded server, and database connections — making it the closest approximation to running the real application in a test. This completeness is both its strength (high confidence) and its cost (slow startup). Spring Boot provides several test slice annotations (@WebMvcTest, @DataJpaTest, @JsonTest) that load only a subset of the context for faster, more focused tests. Knowing when to use each is the difference between a maintainable test suite and one that takes 10 minutes to run.
@SpringBootTest — Full Context Integration Test
webEnvironment controls the embedded server: - `MOCK` (default) — no real server; use MockMvc or WebTestClient - `RANDOM_PORT` — starts a real Tomcat on a random port; use TestRestTemplate or WebTestClient - `DEFINED_PORT` — real Tomcat on server.port - `NONE` — no server at all (test services/repos without HTTP)
Use RANDOM_PORT when you need to test the full HTTP stack including filters, security, and serialisation. Use MOCK for most controller tests — faster and simpler.
// Full integration test — real HTTP stack, random port
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class OrderControllerIntegrationTest {
@Autowired
TestRestTemplate restTemplate; // auto-configured for RANDOM_PORT
@Test
void placeOrder_shouldReturn201AndOrderId() {
OrderRequest request = new OrderRequest("PROD-1", 2);
ResponseEntity<OrderResponse> response = restTemplate.postForEntity(
"/api/orders", request, OrderResponse.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED);
assertThat(response.getBody().getOrderId()).isNotNull();
}
}
// No server — test service layer directly
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
class OrderServiceIntegrationTest {
@Autowired OrderService orderService;
@Autowired OrderRepository orderRepository;
@Test
@Transactional
void placeOrder_shouldPersistOrder() {
Order order = orderService.placeOrder(new OrderRequest("PROD-1", 2));
assertThat(orderRepository.findById(order.getId())).isPresent();
}
}Test Slices — Fast Focused Tests
Spring Boot test slices load only the relevant layer, skipping unneeded auto-configuration. Beans not in scope must be mocked with @MockBean.
- **@WebMvcTest** — loads only MVC layer (controllers, filters, interceptors, @ControllerAdvice). No JPA, no services — mock everything else. - **@DataJpaTest** — loads JPA + H2 in-memory DB. Rolls back each test. Test repository query correctness in isolation. - **@JsonTest** — tests JSON serialisation with Jackson alone. - **@WebFluxTest** — reactive controller slice.
// @WebMvcTest — fast controller test, no Spring Data, no service beans
@WebMvcTest(OrderController.class)
class OrderControllerTest {
@Autowired MockMvc mockMvc;
@MockBean OrderService orderService; // service not loaded — must mock
@Test
void getOrder_whenFound_returns200() throws Exception {
when(orderService.findById(1L))
.thenReturn(Optional.of(new Order(1L, "PENDING", BigDecimal.TEN)));
mockMvc.perform(get("/api/orders/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.status").value("PENDING"))
.andExpect(jsonPath("$.total").value(10.0));
}
@Test
void getOrder_whenNotFound_returns404() throws Exception {
when(orderService.findById(99L)).thenReturn(Optional.empty());
mockMvc.perform(get("/api/orders/99"))
.andExpect(status().isNotFound());
}
}
// @DataJpaTest — test repository queries against real SQL
@DataJpaTest
class OrderRepositoryTest {
@Autowired OrderRepository orderRepository;
@Test
void findByStatus_shouldReturnMatchingOrders() {
orderRepository.save(new Order(null, "PENDING", BigDecimal.TEN));
orderRepository.save(new Order(null, "SHIPPED", BigDecimal.ONE));
List<Order> pending = orderRepository.findByStatus("PENDING");
assertThat(pending).hasSize(1);
assertThat(pending.get(0).getStatus()).isEqualTo("PENDING");
}
}@MockBean, @SpyBean and TestPropertySource
@MockBean replaces a Spring bean with a Mockito mock in the context. @SpyBean wraps the real bean with a Mockito spy (real methods unless stubbed). Use @TestPropertySource or properties attribute to override properties for a specific test.
@SpringBootTest
class PaymentServiceIntegrationTest {
@Autowired PaymentService paymentService;
// Replace the real PaymentGateway with a mock — avoids hitting Stripe in tests
@MockBean PaymentGatewayClient gatewayClient;
// Spy: wraps the real orderRepo — real methods, but can verify calls
@SpyBean OrderRepository orderRepo;
@Test
void charge_shouldSaveOrderOnSuccess() {
when(gatewayClient.charge(any())).thenReturn(new ChargeResult("ch_123", "succeeded"));
Order order = paymentService.charge(new PaymentRequest("ord-1", BigDecimal.TEN));
assertThat(order.getStatus()).isEqualTo("PAID");
verify(orderRepo).save(any(Order.class));
}
}
// Override properties for a test
@SpringBootTest
@TestPropertySource(properties = {
"payment.gateway-url=http://localhost:8099",
"payment.timeout-seconds=1"
})
class PaymentServiceConfigTest { }Key Points to Remember
- 1@SpringBootTest(webEnvironment=RANDOM_PORT) starts a real server — use TestRestTemplate for HTTP calls; best for end-to-end smoke tests.
- 2@WebMvcTest loads only the MVC layer — fast controller tests; mock all service and repository beans with @MockBean.
- 3@DataJpaTest loads only JPA + in-memory H2 and rolls back each test — ideal for testing @Query correctness.
- 4@MockBean replaces the real Spring bean with a Mockito mock; @SpyBean wraps the real bean (real methods unless stubbed).
- 5Prefer test slices over full @SpringBootTest for speed — only use @SpringBootTest for true end-to-end integration tests.
- 6Use @TestPropertySource or @SpringBootTest(properties=…) to override application.yml values for specific tests.
Interview Questions
Sign in to ask AriaWhat is the difference between @SpringBootTest and @WebMvcTest?
When would you use webEnvironment=RANDOM_PORT vs MOCK in @SpringBootTest?
What is the difference between @MockBean and @Mock in Spring Boot tests?
How does @DataJpaTest ensure test isolation?
You have a service that calls an external payment gateway. How do you test it without making real API calls?
Ask Aria about @SpringBootTest
Your personal AI tutor — ask anything about this concept
Revision Status
Personal Notes
Sign in to save personal notes for this topic.
Discussion
Sign in to join the discussion.