嵌套与标签是什么
JUnit 5 的两个组织工具:@Nested 用内部类把用例按场景分组(如「未登录时」「已登录时」),形成可读层级并共享外层生命周期;@Tag 给用例打标签(smoke、integration、slow),配合构建工具筛选执行。组合使用:按业务结构组织代码,按执行策略组织运行。
基本信息
| @Nested | 标注内部类,可非静态,共享外层实例与生命周期 |
|---|---|
| 嵌套限制 | 嵌套类需非静态,可层层嵌套但建议不超两层 |
| @Tag | 类级或方法级打标签,多个标签可叠加 |
| Maven 筛选 | Surefire 配置 groups/includeTags |
| Gradle 筛选 | useJUnitPlatform 配 includeTags/excludeTags |
| @DisplayName | 提供中文或可读标题,进报告不改变方法名 |
结构示例
结构示例
class LoginTest {
@BeforeEach void setUp() { /* 所有嵌套共享的前置 */ }
@Nested
@DisplayName("未登录时")
class WhenAnonymous {
@Test @Tag("smoke")
void redirectsToLoginPage() { ... }
}
@Nested
@DisplayName("已登录时")
class WhenLoggedIn {
@Test
void showsDashboard() { ... }
}
}典型使用场景
- 按状态组织密集用例:同一前置下罗列多个场景
- CI 分层筛选:smoke 快跑守住门禁,integration 慢跑夜间执行
- 共享场景级前置:外层 @BeforeEach 为所有嵌套准备好上下文
- 报告可读性:嵌套结构加 DisplayName 让报告层级清晰
- 渐进重排:先给旧用例打标签,再逐步迁移到 Nested 结构
注解与注意
| 注解 | 作用 | 注意 |
|---|---|---|
| @Nested | 内部类分组 | 外层前置会包住所有嵌套用例 |
| @Tag | 执行筛选标签 | 拼写错误导致用例不被选中 |
| @DisplayName | 可读标题 | 不影响方法名与筛选 |
| @BeforeEach | 用例级前置 | 嵌套下执行次数会放大 |
外层 @BeforeEach 会为每个嵌套用例各执行一次:把重任务放在这里会成性能黑洞,昂贵初始化下沉到更精确的位置。放共享前置前先问一句:它会不会被重复执行很多遍。
标签字符串散落各处是隐患:集中定义常量或约定文档,避免 includeTags 写错导致零用例匹配、流水线静默变绿。
嵌套不是越深越好:四五层之后定位反而变难,两层通常已经能表达业务结构。层级服务于可读性,而不是为了排场。