【问题标题】:What's the purpose of the JUnit 5 @Nested annotationJUnit 5 @Nested 注释的目的是什么
【发布时间】:2016-03-25 13:29:27
【问题描述】:

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

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

【问题讨论】:

标签: java unit-testing junit nested junit5


【解决方案1】:

我只是不明白为什么我们需要在我们的 测试。

@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 中的示例渲染

嵌套的子方法默认折叠:

万一或测试失败或按需您可以展开嵌套的子方法:

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

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

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

      【讨论】:

        【解决方案4】:

        @Nested - 主要从 Junit5 开始,提供我们正在尝试做的功能的延续逻辑。 将业务测试场景拆分为多个类,@nested 正在使用中。

        【讨论】:

          猜你喜欢
          • 2019-03-04
          • 2014-12-11
          • 2020-11-05
          • 2018-07-28
          • 2016-05-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-12-23
          相关资源
          最近更新 更多