| name | spring-testing |
| description | Spring Boot testing with @SpringBootTest, MockMvc, and Testcontainers |
Spring Boot Testing Patterns
Reliable tests for Spring Boot services and APIs.
Prefer slice tests for speed, full context when needed.
Selective Reading Rule
Read only files relevant to the request. Use the content map to focus.
Content Map
| File | Description | When to Read |
|---|
slice-tests.md | @WebMvcTest, @DataJpaTest | Fast feedback |
integration.md | @SpringBootTest, Testcontainers | Real dependencies |
mockmvc.md | MockMvc usage | Controller tests |
test-data.md | Test fixtures, builders | Clean data setup |
Core Patterns
1. Web Slice Tests
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void getUser_returnsUser() throws Exception {
when(userService.findById("u1"))
.thenReturn(Optional.of(new User("u1", "dev@example.com")));
mockMvc.perform(get("/api/v1/users/u1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.email").value("dev@example.com"));
}
}
2. Data JPA Slice
@DataJpaTest
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
void findByEmail_returnsUser() {
var user = userRepository.save(new User("u1", "dev@example.com"));
assertThat(userRepository.findByEmail("dev@example.com")).isPresent();
}
}
3. Full Integration Test
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@Testcontainers
class UserControllerIT {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15");
@Autowired
private TestRestTemplate restTemplate;
@Test
void createUser_returnsCreated() {
var request = new CreateUserRequest("dev@example.com", "Dev");
var response = restTemplate.postForEntity("/api/v1/users", request, UserResponse.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CREATED);
}
}
Decision Checklist
- Slice test for controller/repo?
- Use MockMvc over full context?
- Testcontainers for real DB?
- Avoid shared state between tests?
Anti-Patterns
| Anti-Pattern | Why Bad | Better Approach |
|---|
| @SpringBootTest for all tests | Slow | Slice tests |
| Real DB without isolation | Flaky | Testcontainers |
| Static mutable fixtures | Hidden coupling | Builders/per-test setup |
Related Skills
| Need | Skill |
|---|
| Core Spring patterns | @[skills/spring-boot-patterns] |
| Data access | @[skills/spring-data-jpa] |