JUnit 5 @Nested注释的目的是什么?

sab*_*sab 12 java junit unit-testing nested junit5

在JUnit 5中,有一个新的注释:@Nested.

我理解它是如何工作的,我理解为什么我们使用嵌套类,我只是不明白为什么我们需要在测试中使用嵌套测试类.

dav*_*xxx 20

我只是不明白为什么我们需要在测试中嵌套测试类。

@Nested 组织大型测试课程非常有意义。

典型用例

很多时候,开发团队定义一个测试类来测试。这是一个共享的好习惯,但它也可能使您的测试类变得非常大并且要计算数百行。您确实可以使用多种方法来测试类,每种方法都有多个场景,以及单元测试方法中测试场景所需的一些初始化步骤。
所有这些都会自然地增加测试类的规模。
超过阈值(可能是 500 行左右),问自己是否需要重构就变得合理了。

一个大类(或不是测试类),即使组织得很好,也比多个类以高内聚/关系分组事物更难阅读和维护。
在单元测试案例中,有时会更糟,因为您可能找不到测试场景并在它存在时编写新的测试场景,但由于测试类很大,您没有设法找到它。

@Nested : 解决方案

@Nested通过提供在主(外部)测试类的多个嵌套类中对多个测试方法进行分组的可能性来解决这个问题。
在主(外部)测试类中定义的所有嵌套类的测试方法都作为任何测试方法处理。所以@BeforeEach, @AfterEach, @ExtendWith... 适用于所有这些。
唯一的例外是 @BeforeAll@AfterAll

只有非静态嵌套类(即内部类)才能作为 @Nested测试类。嵌套可以任意深,这些内部类被认为是测试类的家庭有一个例外的正式成员:@BeforeAll@AfterAll方法默认情况下不工作。原因是 Java 不允许在内部类中使用静态成员。但是,可以通过@Nested使用@TestInstance(Lifecycle.PER_CLASS)注释测试类 来规避此限制(请参阅测试实例生命周期)。

通过@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 { 
         //...

    }
}
Run Code Online (Sandbox Code Playgroud)

IDE 中的示例渲染

Nesteds 的子方法默认折叠:

JUnit Eclipse 插件概述

如果或测试失败或按需,您可以展开 Nesteds 的子方法:

展开 JUnit Eclipse 插件失败


Mur*_*nik 9

@Nested注释可以让你有一个内部类,它本质上是一个测试类,可以让你组同一父下的几个测试类(具有相同的初始化).


use*_*610 7

我所有的测试都需要运行数据库服务器。我的大部分测试还需要数据库中有一个 Users 表,才能登录。除此之外,一些测试还需要 Friends 表,才能登录和查询好友。

每个资源都有一个设置和拆卸。我必须启动和停止服务器,创建和删除表。

使用@Nested 注释,我可以将我的测试分组到嵌套类的层次结构中,以便每个测试都可以设置和拆除层次结构中的所有测试。

这种嵌套测试的想法在 Ruby 中很流行。在 Java 中,HierarchicalContextRunner 为 Junit 4 实现。请参阅其页面https://github.com/bechte/junit-hierarchicalcontextrunner/wiki上的理由。