JUnit 5 中的 @TestInstance 注释有什么用?
What use is @TestInstance annotation in JUnit 5?
您能否简单解释一下 @TestInstance
注解及其在 JUnit 5 中的用途?
我想我们可以通过使我们的字段static
.
达到同样的效果
我认为the docs提供了一个有用的总结:
If you would prefer that JUnit Jupiter execute all test methods on the same test instance, simply annotate your test class with @TestInstance(Lifecycle.PER_CLASS). When using this mode, a new test instance will be created once per test class. Thus, if your test methods rely on state stored in instance variables, you may need to reset that state in @BeforeEach or @AfterEach methods.
The "per-class" mode has some additional benefits over the default "per-method" mode. Specifically, with the "per-class" mode it becomes possible to declare @BeforeAll and @AfterAll on non-static methods as well as on interface default methods. The "per-class" mode therefore also makes it possible to use @BeforeAll and @AfterAll methods in @Nested test classes.
但您可能已经读过,您认为将字段设为静态与将字段声明为实例变量并使用 @TestInstance(Lifecycle.PER_CLASS)
.
具有相同的效果,您的想法是正确的
所以,也许“它在 JUnit 5 中如何发挥作用”这个问题的答案是使用 @TestInstance
...
- 明确表达您的意图。可以假设使用 static 关键字是偶然的,而使用
@TestInstance
不太可能是偶然的,或者是粗略的复制粘贴的结果。
- 将管理范围和生命周期的责任委托给框架,而不是必须记住自己管理。
引入此注释是为了减少 运行 单元测试时创建的对象数量。
将 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
添加到您的测试 class 将避免为 class 中的每个测试创建您的 class 的新实例。
当您在同一个测试中有很多测试 class 并且此 class 的实例化很昂贵时,这特别有用。
应谨慎使用此注释。所有单元测试都应该相互隔离和独立。如果其中一项测试更改了测试的状态 class,那么您不应使用此功能。
使您的字段静态化以达到相同的效果并不是一个好主意。它确实会减少创建的对象数量,但是当测试 class 中的所有测试都执行时,它们无法被清理。当你有一个巨大的测试套件时,这可能会导致问题。
@TestInstance
用于配置测试实例的生命周期用于注解测试class或测试接口:
PER_CLASS
: 每个测试都会创建一个新的测试实例class.
PER_METHOD
:将为每个测试方法、测试工厂方法或测试模板方法创建一个新的测试实例。此模式类似于 JUnit 版本 1 到 4 中的行为。
如果 @TestInstance
未在测试 class 或由测试 class 实现的测试接口上显式声明,则生命周期模式将隐式默认为 PER_METHOD
.
将测试实例生命周期模式设置为 PER_CLASS
可启用以下功能:
- 给定测试 class 中的测试方法之间以及测试 class 中的非静态
@BeforeAll
和 @AfterAll
方法之间共享测试实例状态。
@Nested
测试 classes. 中 @BeforeAll
和 @AfterAll
方法的声明
- 关于接口默认方法的
@BeforeAll
和 @AfterAll
声明。
- 使用 Kotlin 编程语言实现的测试 class 中
@BeforeAll
和 @AfterAll
方法的简化声明。
有关详细信息,请参阅 test instance lifecycle 文档。
由于没有人提供合适的代码示例,我想给出一个简单的代码示例如下来理解这个概念,
每个方法示例 - Junit5 中的默认选项
注意两个方法是静态的,否则会引发异常,因为class在每个方法中实例化。
@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));
}
}
每个 Class 样本
请注意,从这两个方法中删除了 static,并且 MathUtil 对象是全局创建的,而不是在方法中创建的,因为 class 仅实例化一次。
@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));
}
}
这在 Kotlin 中编写测试时也很有用,因为它没有静态方法。
因此,不要为 @BeforeAll
或 @AfterAll
使用带有 @JvmStatic
函数的伴生对象,而是创建生命周期 PER_CLASS
并使用 [= 注释常规方法12=] 或 @AfterAll
:
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class MyTest {
@BeforeAll
fun setup() {
println("I am invoked only once")
}
}
使用此方法时,请注意在必要时在 @BeforeEach
或 @AfterEach
方法中重置实例变量。
感谢this article的帮助。
您能否简单解释一下 @TestInstance
注解及其在 JUnit 5 中的用途?
我想我们可以通过使我们的字段static
.
我认为the docs提供了一个有用的总结:
If you would prefer that JUnit Jupiter execute all test methods on the same test instance, simply annotate your test class with @TestInstance(Lifecycle.PER_CLASS). When using this mode, a new test instance will be created once per test class. Thus, if your test methods rely on state stored in instance variables, you may need to reset that state in @BeforeEach or @AfterEach methods.
The "per-class" mode has some additional benefits over the default "per-method" mode. Specifically, with the "per-class" mode it becomes possible to declare @BeforeAll and @AfterAll on non-static methods as well as on interface default methods. The "per-class" mode therefore also makes it possible to use @BeforeAll and @AfterAll methods in @Nested test classes.
但您可能已经读过,您认为将字段设为静态与将字段声明为实例变量并使用 @TestInstance(Lifecycle.PER_CLASS)
.
所以,也许“它在 JUnit 5 中如何发挥作用”这个问题的答案是使用 @TestInstance
...
- 明确表达您的意图。可以假设使用 static 关键字是偶然的,而使用
@TestInstance
不太可能是偶然的,或者是粗略的复制粘贴的结果。 - 将管理范围和生命周期的责任委托给框架,而不是必须记住自己管理。
引入此注释是为了减少 运行 单元测试时创建的对象数量。
将 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
添加到您的测试 class 将避免为 class 中的每个测试创建您的 class 的新实例。
当您在同一个测试中有很多测试 class 并且此 class 的实例化很昂贵时,这特别有用。
应谨慎使用此注释。所有单元测试都应该相互隔离和独立。如果其中一项测试更改了测试的状态 class,那么您不应使用此功能。
使您的字段静态化以达到相同的效果并不是一个好主意。它确实会减少创建的对象数量,但是当测试 class 中的所有测试都执行时,它们无法被清理。当你有一个巨大的测试套件时,这可能会导致问题。
@TestInstance
用于配置测试实例的生命周期用于注解测试class或测试接口:
PER_CLASS
: 每个测试都会创建一个新的测试实例class.PER_METHOD
:将为每个测试方法、测试工厂方法或测试模板方法创建一个新的测试实例。此模式类似于 JUnit 版本 1 到 4 中的行为。
如果 @TestInstance
未在测试 class 或由测试 class 实现的测试接口上显式声明,则生命周期模式将隐式默认为 PER_METHOD
.
将测试实例生命周期模式设置为 PER_CLASS
可启用以下功能:
- 给定测试 class 中的测试方法之间以及测试 class 中的非静态
@BeforeAll
和@AfterAll
方法之间共享测试实例状态。 @Nested
测试 classes. 中 - 关于接口默认方法的
@BeforeAll
和@AfterAll
声明。 - 使用 Kotlin 编程语言实现的测试 class 中
@BeforeAll
和@AfterAll
方法的简化声明。
@BeforeAll
和 @AfterAll
方法的声明
有关详细信息,请参阅 test instance lifecycle 文档。
由于没有人提供合适的代码示例,我想给出一个简单的代码示例如下来理解这个概念,
每个方法示例 - Junit5 中的默认选项 注意两个方法是静态的,否则会引发异常,因为class在每个方法中实例化。
@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));
}
}
每个 Class 样本 请注意,从这两个方法中删除了 static,并且 MathUtil 对象是全局创建的,而不是在方法中创建的,因为 class 仅实例化一次。
@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));
}
}
这在 Kotlin 中编写测试时也很有用,因为它没有静态方法。
因此,不要为 @BeforeAll
或 @AfterAll
使用带有 @JvmStatic
函数的伴生对象,而是创建生命周期 PER_CLASS
并使用 [= 注释常规方法12=] 或 @AfterAll
:
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class MyTest {
@BeforeAll
fun setup() {
println("I am invoked only once")
}
}
使用此方法时,请注意在必要时在 @BeforeEach
或 @AfterEach
方法中重置实例变量。
感谢this article的帮助。