在 JUnit 5 中,有一个新的注解:@Nested
.
我理解注释是如何工作的,我理解为什么我们使用嵌套类,我只是不明白为什么我们需要嵌套测试类。
我只是不明白为什么我们需要在测试中嵌套测试类。
@Nested
组织大型测试课程非常有意义。
典型用例
很多时候,开发团队会逐个定义一个测试类来进行测试。这是一种共享的良好做法,但它也可能使您的测试类非常大并且数以百计行。您确实可以使用多种方法来测试类,每种方法都有多个场景,并且单元测试方法中还需要一些初始化步骤来测试场景。
所有这些自然会增加测试班的规模。
超过一个阈值(可能是 500 行左右),问自己是否需要重构是合理的。
一个大类(无论是否是测试类),即使是组织良好的,也比将具有高内聚/关系的多个类分组更难阅读和维护。
在单元测试用例中,有时可能会更糟,因为您可能找不到测试场景并在它存在时编写一个新场景,但您没有设法找到它,因为测试类很大。
@Nested
: 解决方案
@Nested
通过提供将多个测试方法分组到主(外部)测试类的多个嵌套类中的可能性来解决这个问题。
在主(外部)测试类中定义的所有嵌套类的测试方法都作为任何测试方法处理。所以@BeforeEach
, @AfterEach
, @ExtendWith
... 适用于所有这些。
唯一的例外是 @BeforeAll
and@AfterAll
:
只有非静态嵌套类(即内部类)可以作为
@Nested
测试类。嵌套可以任意深,并且那些内部类被认为是测试类家族的完整成员,但有一个例外:默认情况@BeforeAll
下@AfterAll
方法不起作用。原因是 Java 不允许内部类中的静态成员。@Nested
但是,可以通过使用 ) 注释测试类 来规避此限制@TestInstance(Lifecycle.PER_CLASS
(请参阅测试实例生命周期)。
由于显示名称将用于 IDE 和构建工具中的测试报告,并且可能包含空格、特殊字符甚至表情符号,因此 @Nested
结合使用该@DisplayName
值变得更加精细。String
例子
我有FooService
多种方法和多种场景。我可以在单元测试类的嵌套类中对相同关注的场景进行分组。
在这里,我选择了测试方法对它们进行分组(所以我按场景分组),但如果有意义的话,鉴别器可能是另一回事。
例如 :
public class FooServiceTest {
Foo foo;
// invoked for ALL test methods
@BeforeEach
public void beforeEach() {
Foo foo = new Foo(...);
}
@Nested
@DisplayName("findWith methods")
class FindMethods {
@Test
void findWith_when_X() throws Exception {
//...
foo.findWith(...);
//...
}
@Test
void findWith_when_Y() throws Exception {
//...
foo.findWith(...);
//...
}
@Test
void findWith_when_Z() throws Exception {
//...
foo.findWith(...);
//...
}
}
@Nested
@DisplayName("findAll methods")
class FindAllMethods {
@Test
void findAll_when_X() throws Exception {
//...
foo.findAll(...);
//...
}
@Test
void findAll_when_Y() throws Exception {
//...
foo.findAll(...);
//...
}
@Test
void findAll_when_Z() throws Exception {
//...
foo.findAll(...);
//...
}
}
@Nested
@DisplayName("computeBar methods")
class ComputeBarMethods {
//...
}
@Nested
@DisplayName("saveOrUpdate methods")
class SaveOrUpdateMethods {
//...
}
}
IDE 中的示例渲染
嵌套的子方法默认折叠:
如果或测试失败或根据需要,您可以展开 Nesteds 的子方法:
注释允许您拥有一个本质上是测试类的@Nested
内部类,允许您将多个测试类分组在同一个父级下(具有相同的初始化)。
我所有的测试都需要运行一个数据库服务器。我的大多数测试还需要数据库中的Users表才能登录。除此之外,一些测试需要Friends表才能登录和查询朋友。
每个资源都有一个设置和拆卸。我必须启动和停止服务器,创建和删除表。
使用@Nested 注释,我可以将我的测试分组到嵌套类的层次结构中,以便每个测试都可以设置和拆除层次结构中的所有测试。
这种嵌套测试的想法在 Ruby 中得到了普及。在 Java 中,由 HierarchicalContextRunner 为 Junit 4 实现。请参阅其页面https://github.com/bechte/junit-hierarchicalcontextrunner/wiki上的理由。
@Nested - 主要从 Junit5 开始,提供我们正在尝试做的功能的延续逻辑。将业务测试场景拆分为多个类,@nested 正在使用中。