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

2022-09-01 01:01:39

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

我理解注释是如何工作的,我理解为什么我们使用嵌套类,我只是不明白为什么我们需要嵌套的测试类。


答案 1

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

@Nested组织大型测试类真的很有意义。

典型使用案例

通常,开发团队会逐个类地定义一个测试类来测试。这是一个共同的良好做法,但它也可能使您的测试类非常大,并计算数百行。您确实可以使用多种方法进行测试的类,每个方法具有多个方案,并且单元测试方法中还需要一些初始化步骤来测试方案。
所有这些都将自然而然地增加测试班级的规模。
超过阈值(可能是500行左右),问问自己是否需要重构是合理的。

一个大类(测试类与否),即使组织良好也更难阅读,维护比多个类将具有高内聚力/关系的东西分组。
在单元测试的情况下,情况可能会更糟,因为您可能找不到测试场景并在它存在时编写一个新的测试场景,但是由于测试类很大,因此您无法找到它。

@Nested:解决方案

@Nested解决了这个问题,因为它提供了将多个测试方法分组到一个主(外部)测试类的多个嵌套类中的可能性。
在主(外部)测试类中定义的所有嵌套类的测试方法都像任何测试方法一样处理。所以。。。都适用于所有这些。
唯一的例外是@BeforeAll@AfterAll@BeforeEach@AfterEach@ExtendWith

只有非静态嵌套类(即内部类)可以用作测试类。嵌套可以是任意深度的,并且这些内部类被视为测试类系列的完全成员,但有一个例外:默认情况下方法不起作用。原因是 Java 不允许在内部类中使用静态成员。但是,可以通过使用 ) 对测试类进行批注来规避此限制(请参见测试实例生命周期)。@Nested@BeforeAll@AfterAll@Nested@TestInstance(Lifecycle.PER_CLASS

@DisplayName结合使用会变得更加精细,因为显示名称将用于IDE和构建工具中的测试报告,并且可能包含空格,特殊字符甚至表情符号。@NestedString

我有一个具有多种方法和多个场景。我可以在单元测试类的嵌套类中对具有相同关注点的方案进行分组。
在这里,我选择要测试的方法对它们进行分组(因此我按方案分组),但如果鉴别器有意义,则可能是另一回事。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 中的示例渲染

默认情况下,嵌套的子方法折叠:

Overview in JUnit Eclipse plugin

在测试失败或按需的情况下,您可以展开嵌套的子方法:

Unfold with a failure in JUnit Eclipse plugin


答案 2

该注释允许您拥有一个本质上是测试类的内部类,允许您将多个测试类分组到同一父级(具有相同的初始化)下。@Nested