在JUnit 5中,有一个新得注解:@Nested。我理解注解是如何工作的,我理解为什么我们使用嵌套类,我只是不理解为什么我们需要 nested test 类。
@Nested
wh6knrhe1#
我只是不明白为什么我们需要在测试中使用嵌套测试类。@Nested对于组织大型测试类确实很有意义。
典型使用案例
通常,开发团队会一个类一个类地定义一个测试类。这是一个共享的好习惯,但是它也可能会使你的测试类非常大,需要几百行代码。你确实可以用多个方法来测试类,每个方法都有多个场景,并且在单元测试方法中需要一些初始化步骤来测试场景。所有这些都会自然地增加测试类的规模。超过一个阈值(可能是500行或大约500行),就有理由问自己是否需要重构。一个大类(不管是不是测试类),即使组织得很好也很难阅读,保持比多个类分组的东西之间具有高内聚/关系。在单元测试的情况下,有时情况会更糟,因为您可能找不到一个测试场景,并在它存在时编写一个新的测试场景,但由于测试类太大,您没有设法找到它。
@Nested:解决方案
@Nested通过提供将多个测试方法分组到主(外部)测试类的多个嵌套类中的可能性来解决这个问题。在主(外部)测试类中定义的所有嵌套类的测试方法被作为任何测试方法处理。因此@BeforeEach,@AfterEach,@ExtendWith...被应用于所有这些测试方法。唯一的例外是@BeforeAll和@AfterAll:只有非静态嵌套类(即内部类)可以作为@Nested测试类。嵌套可以是任意深度的,并且这些内部类被认为是测试类家族的完整成员,但有一个例外:默认情况下,@BeforeAll和@AfterAll方法不起作用。原因是Java不允许内部类中有静态成员。但是,可以通过使用@TestInstance(Lifecycle.PER_CLASS注解@Nested测试类来规避此限制。(请参阅测试示例生命周期)。将@Nested与@DisplayName(取String值)结合使用会变得更好,因为显示名称将用于IDE和构建工具中的测试报告,并且可能包含空格、特殊字符,甚至emoji。
@BeforeEach
@AfterEach
@ExtendWith
@BeforeAll
@AfterAll
@TestInstance(Lifecycle.PER_CLASS
@DisplayName
String
示例
我有一个FooService,它有多个方法和多个场景。我可以将相同关注的场景分组到单元测试类的嵌套类中。在这里,我选择了测试方法来对它们进行分组(所以我按场景分组),但是如果有意义的话,鉴别器可以是另一种东西。例如:
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中的示例呈现
默认情况下,Nested的子方法是折叠的:
在测试失败的情况下,或者根据需要,您可以展开Nested的子方法:
5uzkadbs2#
@Nested注解允许您拥有一个内部类,它本质上是一个测试类,允许您将几个测试类分组到同一个父类下(使用相同的初始化)。
ruoxqz4g3#
我所有的测试都需要一个数据库服务器来运行,大部分测试还需要数据库中的一个Users表来登录,除此之外,一些测试还需要Friends表来登录和查询朋友。每个资源都有一个安装和拆卸。我必须启动和停止服务器,创建和删除表。使用@Nested注解,我可以将测试分组到嵌套类的层次结构中,这样每个测试都可以得到层次结构中所有测试的设置和拆卸。这种嵌套测试的思想在Ruby中很流行。在Java中是通过HierarchicalContextRunner在Junit 4中实现的。请参见其页面https://github.com/bechte/junit-hierarchicalcontextrunner/wiki上的理由。
Users
Friends
kgsdhlau4#
@Nested -主要从Junit 5开始,提供了我们正在尝试做的一个特性的延续逻辑。将业务测试场景拆分为多个类,@nested正在使用。
4条答案
按热度按时间wh6knrhe1#
我只是不明白为什么我们需要在测试中使用嵌套测试类。
@Nested
对于组织大型测试类确实很有意义。典型使用案例
通常,开发团队会一个类一个类地定义一个测试类。这是一个共享的好习惯,但是它也可能会使你的测试类非常大,需要几百行代码。你确实可以用多个方法来测试类,每个方法都有多个场景,并且在单元测试方法中需要一些初始化步骤来测试场景。
所有这些都会自然地增加测试类的规模。
超过一个阈值(可能是500行或大约500行),就有理由问自己是否需要重构。
一个大类(不管是不是测试类),即使组织得很好也很难阅读,保持比多个类分组的东西之间具有高内聚/关系。
在单元测试的情况下,有时情况会更糟,因为您可能找不到一个测试场景,并在它存在时编写一个新的测试场景,但由于测试类太大,您没有设法找到它。
@Nested
:解决方案@Nested
通过提供将多个测试方法分组到主(外部)测试类的多个嵌套类中的可能性来解决这个问题。在主(外部)测试类中定义的所有嵌套类的测试方法被作为任何测试方法处理。因此
@BeforeEach
,@AfterEach
,@ExtendWith
...被应用于所有这些测试方法。唯一的例外是
@BeforeAll
和@AfterAll
:只有非静态嵌套类(即内部类)可以作为
@Nested
测试类。嵌套可以是任意深度的,并且这些内部类被认为是测试类家族的完整成员,但有一个例外:默认情况下,@BeforeAll
和@AfterAll
方法不起作用。原因是Java不允许内部类中有静态成员。但是,可以通过使用@TestInstance(Lifecycle.PER_CLASS
注解@Nested
测试类来规避此限制。(请参阅测试示例生命周期)。将
@Nested
与@DisplayName
(取String
值)结合使用会变得更好,因为显示名称将用于IDE和构建工具中的测试报告,并且可能包含空格、特殊字符,甚至emoji。示例
我有一个
FooService
,它有多个方法和多个场景。我可以将相同关注的场景分组到单元测试类的嵌套类中。在这里,我选择了测试方法来对它们进行分组(所以我按场景分组),但是如果有意义的话,鉴别器可以是另一种东西。
例如:
IDE中的示例呈现
默认情况下,Nested的子方法是折叠的:
在测试失败的情况下,或者根据需要,您可以展开Nested的子方法:
5uzkadbs2#
@Nested
注解允许您拥有一个内部类,它本质上是一个测试类,允许您将几个测试类分组到同一个父类下(使用相同的初始化)。ruoxqz4g3#
我所有的测试都需要一个数据库服务器来运行,大部分测试还需要数据库中的一个
Users
表来登录,除此之外,一些测试还需要Friends
表来登录和查询朋友。每个资源都有一个安装和拆卸。我必须启动和停止服务器,创建和删除表。
使用
@Nested
注解,我可以将测试分组到嵌套类的层次结构中,这样每个测试都可以得到层次结构中所有测试的设置和拆卸。这种嵌套测试的思想在Ruby中很流行。在Java中是通过HierarchicalContextRunner在Junit 4中实现的。请参见其页面https://github.com/bechte/junit-hierarchicalcontextrunner/wiki上的理由。
kgsdhlau4#
@Nested -主要从Junit 5开始,提供了我们正在尝试做的一个特性的延续逻辑。将业务测试场景拆分为多个类,@nested正在使用。