Junit 测试如何在后台工作?
How does Junit test work in the background?
我最近才开始使用 Junit 测试,所以如果我的术语不正确,请原谅。据我所知,如果我们用 @test 注释它,这些方法就会成为测试方法,我们可以通过单击旁边的播放按钮,用 IDE(我正在使用 Intellij)运行它。在后台,它可能会实例化 Test class 和 运行 所选方法的实例。我的问题是,在下面的示例中,如果 test1 和 test2 都使用和编辑同一测试实例的相同 hello 字符串 class,因为 test2 运行s 在 test1 之后,它应该打印编辑的你好字符串的版本?即:test2 应该打印“1”。但在这种情况下,它会打印一个空字符串。这是为什么?
class Test{
private String hello = "";
@Test
void test1() {
hello = hello + "1";
System.out.println(hello);
}
@Test
void test2() {
System.out.println(hello)
}
}
在大多数情况下,单元测试不应依赖于顺序或执行。
默认情况下,JUnit 不会保证执行顺序,在这种情况下,test1
可以在 test2
之后或之前执行。
对于测试,您可以使用 @BeforeEach
或 @BeforeAll
在测试之前执行一些代码。
您也可以使用@Order(1)
来运行 强制执行测试命令。但是我会再次强烈推荐它,除非是在非常特殊的情况下。
这是由于测试的生命周期造成的。
您猜对了,实际上 JUnit 实例化了测试的 Class(在本例中为 class Test
)。
换句话说,在 JUnit 代码的某处有一行:
Test test = new Test()
(在实际代码中它使用了反射,但为了问题的缘故并不重要)。
然后是 运行 测试方法,到目前为止一切顺利 - 你是对的:
Test test = new Test();
test.test1();
test.test2();
// handle failures, exceptions, etc.
但是,JUnit 的设计方式是在运行每个测试方法 之前实例化测试的class。这是 JUnit 框架的设计决定。
因此,JUnit 中发生的事情的“更准确”表示如下所示:
Test test = new Test();
test.test1();
....
test = new Test();
test.test2();
这是 JUnit 的默认行为,所有数据字段都会为每个测试一遍又一遍地实例化,它保证 test1
打印 1
test2
打印一个空字符串。
无论实际测试执行的顺序如何,都会发生这种情况。
现在,可以通过在测试 class 上使用 @TestInstance(LifeCycle.PER_CLASS)
注释来改变这种行为,但这是一个非常高级的东西。它将指示 JUnit 引擎只创建一个单独的 class Test 对象和 运行 其中的所有测试方法。因此,如果一个测试方法将更改 class Test
中定义的数据字段,则另一个测试实际上会看到此更改。
如果您有兴趣了解有关 @TestInstance
的更多信息 - 请考虑阅读 this article for example
我最近才开始使用 Junit 测试,所以如果我的术语不正确,请原谅。据我所知,如果我们用 @test 注释它,这些方法就会成为测试方法,我们可以通过单击旁边的播放按钮,用 IDE(我正在使用 Intellij)运行它。在后台,它可能会实例化 Test class 和 运行 所选方法的实例。我的问题是,在下面的示例中,如果 test1 和 test2 都使用和编辑同一测试实例的相同 hello 字符串 class,因为 test2 运行s 在 test1 之后,它应该打印编辑的你好字符串的版本?即:test2 应该打印“1”。但在这种情况下,它会打印一个空字符串。这是为什么?
class Test{
private String hello = "";
@Test
void test1() {
hello = hello + "1";
System.out.println(hello);
}
@Test
void test2() {
System.out.println(hello)
}
}
在大多数情况下,单元测试不应依赖于顺序或执行。
默认情况下,JUnit 不会保证执行顺序,在这种情况下,test1
可以在 test2
之后或之前执行。
对于测试,您可以使用 @BeforeEach
或 @BeforeAll
在测试之前执行一些代码。
您也可以使用@Order(1)
来运行 强制执行测试命令。但是我会再次强烈推荐它,除非是在非常特殊的情况下。
这是由于测试的生命周期造成的。
您猜对了,实际上 JUnit 实例化了测试的 Class(在本例中为 class Test
)。
换句话说,在 JUnit 代码的某处有一行:
Test test = new Test()
(在实际代码中它使用了反射,但为了问题的缘故并不重要)。
然后是 运行 测试方法,到目前为止一切顺利 - 你是对的:
Test test = new Test();
test.test1();
test.test2();
// handle failures, exceptions, etc.
但是,JUnit 的设计方式是在运行每个测试方法 之前实例化测试的class。这是 JUnit 框架的设计决定。
因此,JUnit 中发生的事情的“更准确”表示如下所示:
Test test = new Test();
test.test1();
....
test = new Test();
test.test2();
这是 JUnit 的默认行为,所有数据字段都会为每个测试一遍又一遍地实例化,它保证 test1
打印 1
test2
打印一个空字符串。
无论实际测试执行的顺序如何,都会发生这种情况。
现在,可以通过在测试 class 上使用 @TestInstance(LifeCycle.PER_CLASS)
注释来改变这种行为,但这是一个非常高级的东西。它将指示 JUnit 引擎只创建一个单独的 class Test 对象和 运行 其中的所有测试方法。因此,如果一个测试方法将更改 class Test
中定义的数据字段,则另一个测试实际上会看到此更改。
如果您有兴趣了解有关 @TestInstance
的更多信息 - 请考虑阅读 this article for example