JUnit 5中的@TestInstance注释有什么用?

时间:2018-09-28 08:55:26

标签: java unit-testing testing junit junit5

您能否简单解释一下<CodeCoverage> <Sources> <Include> <Source>.*\\My\.Solution\.Name\.Space\\.*</Source> <!-- ie: include *\My.Solution.Name.Space\* --> </Include> <Exclude> <Source>.*\\My\.Solution\.Name\.Space\\Tests\\.*</Source> <!-- ie: exclude *\My.Solution.Name.Space\Tests\* --> </Exclude> </Sources> <!-- removed for brevity --> <CodeCoverage> 注释及其在JUnit 5中的有用性?

我认为我们可以通过将字段设置为静态 来达到相同的效果。

5 个答案:

答案 0 :(得分:6)

我认为the docs提供了有用的摘要:

  

如果您希望JUnit Jupiter在同一个测试实例上执行所有测试方法,只需使用@TestInstance(Lifecycle.PER_CLASS)注释您的测试类。使用此模式时,每个测试类将创建一个新的测试实例。因此,如果您的测试方法依赖于实例变量中存储的状态,则可能需要在@BeforeEach或@AfterEach方法中重置该状态。

     

与默认的“按方法”模式相比,“按类”模式具有一些其他优点。具体来说,使用“按类”模式可以在非静态方法以及接口默认方法上声明@BeforeAll和@AfterAll。因此,“每类”模式还可以在@Nested测试类中使用@BeforeAll和@AfterAll方法。

但是您可能已经读过了,并且认为将字段设为静态与将字段声明为实例变量并使用@TestInstance(Lifecycle.PER_CLASS)具有相同的效果。

因此,“如何在JUnit 5中发挥作用”这个问题的答案可能是使用@TestInstance ...

  • 明确表示您的意图。可以假设使用static关键字是偶然的,而使用@TestInstance则不太可能是偶然的,或者是尽管复制n粘贴较少的结果。
  • 委托管理范围和生命周期并清理框架的责任,而不必记住自己进行管理。

答案 1 :(得分:2)

引入此注释是为了减少运行单元测试时创建的对象数量。

在测试类中添加@TestInstance(TestInstance.Lifecycle.PER_CLASS)可以避免为该类中的每个测试创建新的类实例。 当您在同一个测试类中有很多测试并且此类的实例化非常昂贵时,这特别有用。

应谨慎使用此注释。所有单元测试都应隔离并且彼此独立。如果其中一项测试更改了测试类的状态,则您不应使用此功能。

使字段保持静态以达到相同效果不是一个好主意。确实可以减少创建的对象的数量,但是当执行测试类中的所有测试时,无法清除它们。当您拥有庞大的测试套件时,这可能会导致问题。

答案 2 :(得分:2)

由于没有人提供适当的编码示例,因此我想举一个简单的代码示例,以了解其概念,

每个方法示例-Junit5中的默认选项 请注意,两个方法是静态的,否则将触发异常,因为类在每个方法中都实例化。

@TestInstance(Lifecycle.PER_METHOD)
public class MathUtilTestPerMethod {

    MathUtil util;

    @BeforeAll
    static void beforeAllInit() {
        System.out.println("running before all");
    }

    @AfterAll
    static void afterAllCleanUp() {
        System.out.println("running after all");
    }

    @BeforeEach
    void init() {
        util = new MathUtil();
        System.out.println("running before each...");
    }

    @AfterEach
    void cleanUp() {
        System.out.println("running after each...");
    }

    @Test
    void testSum() {
        assertEquals(2, util.addtwoNumbers(1, 1));
    }

}

每个班级样本 请注意,从这两个方法中删除了静态方法,并且不在类中全局创建MathUtil对象,因为类仅实例化一次。

@TestInstance(Lifecycle.PER_CLASS)
public class MathUtilTestPerClass {

    MathUtil util = new MathUtil();

    @BeforeAll
    void beforeAllInit() {
        System.out.println("running before all");
    }

    @AfterAll
    void afterAllCleanUp() {
        System.out.println("running after all");
    }

    @BeforeEach
    void init() {
        System.out.println("running before each...");
    }

    @AfterEach
    void cleanUp() {
        System.out.println("running after each...");
    }

    @Test
    void testSum() {
        assertEquals(2, util.addtwoNumbers(1, 1));
    }

}

答案 3 :(得分:1)

@TestInstance用于为带注释的测试类或测试接口配置测试实例的生命周期:

如果未在测试类或由测试类实现的测试接口上显式声明@TestInstance,则生命周期模式将隐式默认为PER_METHOD


将测试实例生命周期模式设置为PER_CLASS会启用以下功能:

  • 给定测试类中的测试方法之间以及测试类中的非静态@BeforeAll@AfterAll方法之间的共享测试实例状态。
  • @BeforeAll测试类中声明@AfterAll@Nested方法。
  • 在接口默认方法上声明@BeforeAll@AfterAll
  • 使用Kotlin编程语言实现的测试类中的@BeforeAll@AfterAll方法的简化声明。

有关更多详细信息,请参见test instance lifecycle文档。

答案 4 :(得分:0)

这在用 Kotlin 语言编写测试时也很有用,因为它没有静态方法。

因此,不要将带有 @JvmStatic 乐趣的伴随对象用于 @BeforeAll@AfterAll,而是使生命周期 PER_CLASS 并使用 {{1} 注释常规方法} 或 @BeforeAll

@AfterAll

使用这种方法时,如果需要,请小心在 @TestInstance(TestInstance.Lifecycle.PER_CLASS) class MyTest { @BeforeAll fun setup() { println("Invoked only once") } } @BeforeEach 方法中重置实例变量。

感谢this article