JUnit 5@Nested注解的用途是什么

wydwbb8l  于 2022-11-11  发布在  其他
关注(0)|答案(4)|浏览(531)

在JUnit 5中,有一个新得注解:@Nested
我理解注解是如何工作的,我理解为什么我们使用嵌套类,我只是不理解为什么我们需要 nested test 类。

wh6knrhe

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,它有多个方法和多个场景。我可以将相同关注的场景分组到单元测试类的嵌套类中。
在这里,我选择了测试方法来对它们进行分组(所以我按场景分组),但是如果有意义的话,鉴别器可以是另一种东西。
例如:

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的子方法:

5uzkadbs

5uzkadbs2#

@Nested注解允许您拥有一个内部类,它本质上是一个测试类,允许您将几个测试类分组到同一个父类下(使用相同的初始化)。

ruoxqz4g

ruoxqz4g3#

我所有的测试都需要一个数据库服务器来运行,大部分测试还需要数据库中的一个Users表来登录,除此之外,一些测试还需要Friends表来登录和查询朋友。
每个资源都有一个安装和拆卸。我必须启动和停止服务器,创建和删除表。
使用@Nested注解,我可以将测试分组到嵌套类的层次结构中,这样每个测试都可以得到层次结构中所有测试的设置和拆卸。
这种嵌套测试的思想在Ruby中很流行。在Java中是通过HierarchicalContextRunner在Junit 4中实现的。请参见其页面https://github.com/bechte/junit-hierarchicalcontextrunner/wiki上的理由。

kgsdhlau

kgsdhlau4#

@Nested -主要从Junit 5开始,提供了我们正在尝试做的一个特性的延续逻辑。将业务测试场景拆分为多个类,@nested正在使用。

相关问题