Overview
Spring Boot tests come in layers. Use the smallest annotation that loads only what you need. Full context is slow; slices load just one layer.
Official: Spring Boot Testing.
Table of contents
- Annotation cheat sheet
@SpringBootTest@WebMvcTest@DataJpaTest@MockBeanand context caching- Testcontainers
@DynamicPropertySource- Interview questions
- Summary
1. Annotation cheat sheet
| Annotation | Loads |
|---|---|
@SpringBootTest |
Full (or near-full) application context |
@WebMvcTest |
Web layer only (controllers, Jackson, validation) |
@DataJpaTest |
JPA repositories + embedded DB |
@JsonTest |
Jackson serialisation only |
@RestClientTest |
One HTTP client + its mocks |
2. @SpringBootTest
Loads everything. Use for integration tests where you genuinely need wiring.
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class OrderApiIT { ... }
webEnvironment options:
MOCK(default) — mock servlet env, no real port.RANDOM_PORT— real Tomcat on a random port (good forTestRestTemplate/WebTestClient).
Slow → use sparingly. Use slices first.
3. @WebMvcTest
Tests controllers without booting the full app.
@WebMvcTest(OrderController.class)
class OrderControllerTest {
@Autowired MockMvc mvc;
@MockBean OrderService service;
@Test
void returns404() throws Exception {
when(service.find(1L)).thenThrow(new NotFoundException());
mvc.perform(get("/api/orders/1"))
.andExpect(status().isNotFound());
}
}
Loads @RestController, validation, Jackson — not services or JPA.
4. @DataJpaTest
Tests repositories against an embedded DB (H2 by default).
@DataJpaTest
class OrderRepositoryTest {
@Autowired OrderRepository orders;
// test queries
}
Use @AutoConfigureTestDatabase(replace = NONE) to keep your real DB driver (e.g. when using Testcontainers).
5. @MockBean and context caching
Spring caches test contexts between tests for speed. Each distinct combination of @MockBean becomes a new cache key, so many varied mock setups cause context churn and slow suites.
Rule of thumb: prefer plain Mockito unit tests when no Spring wiring is needed. Use @MockBean only when Spring must inject the mock into the system under test.
6. Testcontainers
Spin up a real Postgres/Kafka/Redis in Docker for the test:
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
@Testcontainers
class OrderRepositoryIT {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16");
@DynamicPropertySource
static void props(DynamicPropertyRegistry r) {
r.add("spring.datasource.url", postgres::getJdbcUrl);
r.add("spring.datasource.username", postgres::getUsername);
r.add("spring.datasource.password", postgres::getPassword);
}
}
Real SQL dialect → catches issues H2 hides.
7. @DynamicPropertySource
Injects property values into Spring’s Environment before the context refreshes. Standard pattern for Testcontainers URLs/ports.
8. Interview questions
Q: @WebMvcTest vs @SpringBootTest?
A: @WebMvcTest loads only the web layer (fast, focused). @SpringBootTest loads everything (slow, integration).
Q: Why can @MockBean slow down a test suite?
A: Each unique mock combination triggers a new test context, which forces a context restart.
Q: What is Testcontainers for? A: Running real databases, Kafka, Redis in Docker during integration tests so you don’t rely on H2 quirks.
Q: What does @DynamicPropertySource do?
A: Adds properties to Spring’s environment before context refresh — used for container URLs/ports.
9. Summary
| Annotation | Loads | Speed |
|---|---|---|
@SpringBootTest |
Everything | Slow |
@WebMvcTest |
Web slice | Fast |
@DataJpaTest |
JPA + DB | Medium |
| Plain Mockito | Nothing Spring | Fastest |
Next steps
Happy Learning