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

e0uiprwp  于 2022-11-11  发布在  其他
关注(0)|答案(5)|浏览(233)

您能否简单解释一下@TestInstance注解以及它在JUnit 5中的作用?
我认为我们可以通过**使我们的字段 *static***达到同样的效果。

4c8rllxm

4c8rllxm1#

我认为这些文档提供了一个有用的总结:
如果您希望JUnit Jupiter在同一个测试示例上执行所有测试方法,只需使用@TestInstance(Lifecycle.PER_CLASS)注解您的测试类。使用此模式时,每个测试类将创建一个新的测试示例。因此,如果您的测试方法依赖于示例变量中存储的状态,您可能需要在@BeforeEach或@AfterEach方法中重置该状态。
与默认的“每方法”模式相比,“每类”模式有一些额外的好处。特别是,使用“每类”模式,可以在非静态方法和接口默认方法上声明@BeforeAll和@AfterAll。因此,“每类”模式也可以在@嵌套测试类中使用@BeforeAll和@AfterAll方法。
但是您可能已经读过这篇文章,并且您认为将字段设置为静态与将字段声明为示例变量并使用@TestInstance(Lifecycle.PER_CLASS)具有相同的效果,这是正确的。
因此,对于“它在JUnit 5中如何有用”这个问题的答案可能是使用@TestInstance...

  • 可以假定static关键字的使用是偶然的,而@TestInstance的使用不太可能是偶然的,或者是未经考虑的复制和粘贴的结果。
  • 将管理范围和生命周期以及清理的责任委托给框架,而不必记住自己来管理。
67up9zun

67up9zun2#

引入此注解是为了减少在运行单元测试时创建的对象的数量。
@TestInstance(TestInstance.Lifecycle.PER_CLASS)添加到测试类中可以避免为类中的每个测试创建类的新示例。当在同一个测试类中有很多测试并且该类的示例化开销很大时,这一点特别有用。
应谨慎使用此注解。所有单元测试都应相互隔离。如果其中一个测试更改了测试类的状态,则不应使用此功能。
将字段设为静态以达到相同的效果并不是一个好主意。这确实会减少创建的对象的数量,但在执行测试类中的所有测试时无法清除这些对象。当您有一个巨大的测试套件时,这可能会导致问题。

gblwokeq

gblwokeq3#

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

  • PER_CLASS:每个测试类将创建一次新的测试示例。
  • PER_METHOD:将为每个测试方法、测试工厂方法或测试模板方法创建一个新的测试示例。此模式类似于JUnit版本1到4中的行为。

如果@TestInstance没有在测试类或由测试类实现的测试接口上显式声明,则生命周期模式将隐式默认为PER_METHOD
将测试示例生命周期模式设置为PER_CLASS将启用以下功能:

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

有关详细信息,请参阅测试示例生命周期文档。

wz1wpwve

wz1wpwve4#

由于没有人提供一个合适的编码例子,我想给予一个简单的代码样本,如下理解的概念,

Per Method Sample -Junit 5中的默认选项请注意,两个方法是静态的,否则将引发异常,因为类在每个方法中示例化。

@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));
    }

}

每个类示例请注意,从两个方法中删除了static,并全局创建了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));
    }

}
zujrkrfu

zujrkrfu5#

这在用Kotlin编写测试时也很有用(因为它没有静态方法)。
因此,不要将包含@JvmStatic函数的伴随对象用于@BeforeAll@AfterAll,而是将生命周期设置为PER_CLASS,并使用@BeforeAll@AfterAll注解常规方法:

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class MyTest {

    @BeforeAll
    fun setup() {
        println("I am invoked only once")
    }
}

使用此方法时,如有必要,请小心重置@BeforeEach@AfterEach函数中的示例变量。
感谢this article的帮助。

相关问题