使用@Nested编写嵌套测试的核心是按业务语义分层组织测试类,每个@Nested类代表一个独立但上下文连贯的业务阶段,必须是非静态内部类以访问外部实例字段,并通过@BeforeEach设置层级专属前置条件,配合@DisplayName提升可读性,嵌套深度建议不超过两层。

用 @Nested 编写嵌套测试,核心是按业务语义分层组织测试类,让每个层级聚焦一个明确场景,同时保持状态隔离与可读性。
按业务维度建模嵌套结构
不要按技术类型(如“单元测试”“集成测试”)划分,而应还原真实业务流程。例如订单服务可拆为:
- @Nested class 创建订单:覆盖用户名为空、邮箱格式错误、年龄不合规等分支
- @Nested class 支付流程:区分支付成功、余额不足、超时失败等子场景
- @Nested class 发货校验:验证库存扣减、地址合法性、物流接口异常等
每个 @Nested 类代表一个独立但上下文连贯的业务阶段,外层类只负责共享资源(如 mock 的 service 实例),不放具体 @Test 方法。
正确声明嵌套类并管理生命周期
@Nested 类必须是非静态内部类,才能访问外部类的实例字段(比如被测对象、测试数据工厂)。每个嵌套类可拥有自己的准备逻辑:
- 在嵌套类内使用
@BeforeEach设置该层级专属前置条件(如先创建草稿订单,再进入支付环节) - 避免跨嵌套类直接调用字段或方法;状态传递靠构造参数或静态工具类
- 不要用
static修饰嵌套类,否则会失去对外部实例成员的访问能力,也破坏生命周期绑定
用 @DisplayName 提升可读性
测试报告和 IDE 导航依赖清晰的显示名,而非代码命名规范:
- 在外层类或
@Nested类上加@DisplayName("退款审核流程") - 在
@Test方法上加@DisplayName("拒绝理由为空时应抛出异常") - 最终在 IntelliJ 或 Maven Surefire 报告中呈现为:“退款审核流程 › 拒绝理由为空时应抛出异常”,接近自然语言描述
控制嵌套深度,保持可维护性
两层嵌套(如 OrderServiceTest > PaymentFlow > whenPaySuccessThenOrderConfirmed)足够表达多数业务关系:
- 三层虽支持,但会增加理解成本,也易违反单一职责原则
- JUnit 不支持四层及以上嵌套——编译可能通过,但运行时行为不可靠
- 若发现需要三层以上,建议重新审视业务模型是否过度复杂,或考虑拆分为多个顶层测试类











