我只是不明白为什么我们需要在我们的
测试。
@Nested 组织大型测试课程非常有意义。
典型用例
开发人员团队通常会逐个定义测试类进行测试。
这是一种共享的良好做法,但它也可能使您的测试类非常大并且数以百计。您确实可以使用多种方法来测试类,每种方法都有多个场景,以及单元测试方法中所需的一些初始化步骤来测试场景。
所有这些自然会增加测试类的规模。
超过一个阈值(可能是 500 行左右),问自己是否需要重构是合理的。
一个大类(无论是否是测试类),即使是组织良好的类也比将具有高凝聚力/关系的多个类分组更难阅读和维护。
在单元测试用例中,有时可能会更糟,因为您可能找不到测试场景并在它存在时编写新的场景,但您没有设法找到它,因为测试类很大。
@Nested:解决方案
@Nested 通过提供将多个测试方法分组到主(外部)测试类的多个嵌套类中的可能性来解决此问题。
在主(外部)测试类中定义的所有嵌套类的测试方法都作为任何测试方法处理。所以@BeforeEach, @AfterEach, @ExtendWith... 都申请了。
The single exception is @BeforeAll and @AfterAll :
只有非静态嵌套类(即内部类)可以用作
@Nested 测试类。嵌套可以任意深,而那些内
类被认为是测试类家族的正式成员
除了一个例外:@BeforeAll 和 @AfterAll 方法不起作用
默认。原因是Java不允许静态成员
内部类。但是,可以通过以下方式规避此限制
注释 @Nested 测试类
@TestInstance(Lifecycle.PER_CLASS)(参见测试实例生命周期)。
将@Nested 与采用String 值的@DisplayName 结合使用变得更加精细,因为显示名称将用于IDE 和构建工具中的测试报告,并且可能包含空格、特殊字符甚至表情符号。
示例
我有一个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 中的示例渲染
嵌套的子方法默认折叠:
万一或测试失败或按需您可以展开嵌套的子方法: