关于 spring-boot-test-patterns
为 Spring Boot 开发者提供测试模式指南,涵盖 Mockito、JUnit 5 和 Testcontainers。按单元、切片与集成测试分层,帮助选择测试范围并控制上下文开销。
主要功能
- 01单元测试与 Mockito 模式
- 02按层使用 Spring 测试切片
- 03MockMvc REST API 测试
- 04Testcontainers 与服务连接
- 05依赖配置及 CI/CD 指南
适用场景
- 01为服务或仓储编写隔离测试
- 02使用真实数据库运行集成测试
- 03验证 REST 控制器与 API
- 04配置自动化测试流水线
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ giuseppe-trisciuoglio/ developer-kit --skill spring-boot-test-patterns安装后在 Claude Code 中输入/spring-boot-test-patterns确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/api-reference.mdbest-practices.mdci-cd-configuration.mdslice-testing.mdtest-dependencies.mdtestcontainers-setup.mdunit-testing.mdworkflow-patterns.md详细介绍
Spring Boot 测试模式
概述
全面介绍如何使用 JUnit 5、Mockito、Testcontainers 和经过性能优化的切片测试模式,为 Spring Boot 应用编写健壮的测试套件。
适用场景
- 为具有模拟依赖项的服务或仓库编写单元测试
- 使用 Testcontainers 通过真实数据库实现集成测试
- 使用
@WebMvcTest或 MockMvc 测试 REST API - 在 Spring Boot 3.5+ 中配置
@ServiceConnection来管理容器
快速参考
| 测试类型 | 注解 | 目标耗时 | 用例 |
|---|---|---|---|
| 单元测试 | @ExtendWith(MockitoExtension.class) | < 50ms | 不加载 Spring 上下文的业务逻辑测试 |
| 仓库测试 | @DataJpaTest | < 100ms | 在最小上下文中测试数据库操作 |
| 控制器测试 | @WebMvcTest / @WebFluxTest | < 100ms | REST API 层测试 |
| 集成测试 | @SpringBootTest | < 500ms | 使用容器加载完整应用上下文 |
| Testcontainers | @ServiceConnection / @Testcontainers | 不定 | 真实数据库/消息代理容器 |
核心概念
测试架构理念
- 单元测试 — 快速、隔离,不加载 Spring 上下文(< 50ms)
- 切片测试 — 为特定层加载最小 Spring 上下文(< 100ms)
- 集成测试 — 使用真实依赖项加载完整 Spring 上下文(< 500ms)
关键注解
Spring Boot 测试:
@SpringBootTest— 完整应用上下文(谨慎使用)@DataJpaTest— 仅测试 JPA 组件(仓库、实体)@WebMvcTest— 仅测试 MVC 层(控制器、@ControllerAdvice)@WebFluxTest— 仅测试 WebFlux 层(响应式控制器)@JsonTest— 仅测试 JSON 序列化组件
Testcontainers:
@ServiceConnection— 将 Testcontainer 接入 Spring Boot(3.5+)@DynamicPropertySource— 在运行时注册动态属性@Testcontainers— 启用 Testcontainers 生命周期管理
操作指南
1. 单元测试模式
使用模拟依赖项测试业务逻辑:
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
void shouldFindUserByIdWhenExists() {
when(userRepository.findById(1L)).thenReturn(Optional.of(user));
Optional<User> result = userService.findById(1L);
assertThat(result).isPresent();
verify(userRepository).findById(1L);
}
}
高级模式请参阅 unit-testing.md。
2. 切片测试模式
使用针对特定层的测试切片:
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@TestContainerConfig
class UserRepositoryIntegrationTest {
@Autowired
private UserRepository userRepository;
@Test
void shouldSaveAndRetrieveUser() {
User saved = userRepository.save(user);
assertThat(userRepository.findByEmail("[email protected]")).isPresent();
}
}
所有切片模式请参阅 slice-testing.md。
3. REST API 测试模式
使用 MockMvc 测试控制器:
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void shouldGetUserById() throws Exception {
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.email").value("[email protected]"));
}
}
4. 使用 @ServiceConnection 配置 Testcontainers
在 Spring Boot 3.5+ 中配置容器:
@TestConfiguration
public class TestContainerConfig {
@Bean
@ServiceConnection
public PostgreSQLContainer<?> postgresContainer() {
return new PostgreSQLContainer<>("postgres:16-alpine");
}
}
在测试类上使用 @Import(TestContainerConfig.class)。
详细配置请参阅 testcontainers-setup.md。
5. 添加依赖项
添加所需的测试依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.19.0</version>
<scope>test</scope>
</dependency>
完整依赖项列表请参阅 test-dependencies.md。
6. 配置 CI/CD
设置 GitHub Actions 以自动运行测试:
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
docker:
image: docker:20-dind
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
- name: Run tests
run: ./mvnw test
完整的 CI/CD 模式请参阅 ci-cd-configuration.md。
验证检查点
实现测试后,请验证:
- 容器正在运行:
docker ps(查找 testcontainer 镜像) - 上下文已加载:检查启动日志中的 "Started Application in X.XX seconds"
- 测试隔离性:单独运行测试,并确认没有相互污染
示例
使用 @ServiceConnection 的完整集成测试
@SpringBootTest
@Import(TestContainerConfig.class)
class OrderServiceIntegrationTest {
@Autowired
private OrderService orderService;
@Autowired
private UserRepository userRepository;
@Test
void shouldCreateOrderForExistingUser() {
User user = userRepository.save(User.builder()
.email("[email protected]")
.build());
Order order = orderService.createOrder(user.getId(), List.of(
new OrderItem("SKU-001", 2)
));
assertThat(order.getId()).isNotNull();
assertThat(order.getStatus()).isEqualTo(OrderStatus.PENDING);
}
}
使用真实数据库的 @DataJpaTest
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@TestContainerConfig
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
void shouldFindByEmail() {
userRepository.save(User.builder()
.email("[email protected]")
.build());
assertThat(userRepository.findByEmail("[email protected]"))
.isPresent();
}
}
完整的端到端示例请参阅 workflow-patterns.md。
最佳实践
- 使用合适的测试类型:仓库使用
@DataJpaTest,控制器使用@WebMvcTest,仅在完整集成测试中使用@SpringBootTest - 在 Spring Boot 3.5+ 中优先使用
@ServiceConnection,相比@DynamicPropertySource,它能更简洁地管理容器 - 确保测试具有确定性:在
@BeforeEach中显式初始化所有测试数据 - 按层组织测试:按层分组测试,以最大限度地利用上下文缓存
- 在 JVM 级别复用 Testcontainers(
withReuse(true)+TESTCONTAINERS_REUSE_ENABLE=true) - 避免使用
@DirtiesContext:它会强制重建上下文,显著降低性能 - 模拟外部服务,仅在必要时使用真实数据库
- 性能目标:单元测试 < 50ms,切片测试 < 100ms,集成测试 < 500ms
限制和警告
- 除非绝对必要,否则切勿使用
@DirtiesContext(它会强制重建上下文) - 避免混用不同配置的
@MockBean(会创建独立的上下文) - Testcontainers 需要 Docker;确保 CI/CD 流水线支持 Docker
- 不要依赖测试执行顺序;每个测试都必须相互独立
- 谨慎使用
@TestPropertySource(会创建独立的上下文) - 不要在单元测试中使用
@SpringBootTest;请改用纯 Mockito - 不同的
@MockBean配置可能会使上下文缓存失效 - 避免在测试中使用静态可变状态(会导致测试结果不稳定)
参考资料
- test-dependencies.md — Maven/Gradle 测试依赖
- unit-testing.md — 使用 Mockito 模式进行单元测试
- slice-testing.md — 仓库、控制器和 JSON 切片测试
- testcontainers-setup.md — Testcontainers 配置模式
- ci-cd-configuration.md — GitHub Actions、GitLab CI、Docker Compose
- api-reference.md — 完整的测试注解和工具
- best-practices.md — 测试模式和优化
- workflow-patterns.md — 完整的集成测试示例
评论
支持 Markdown