【问题标题】:How does Junit test work in the background?Junit测试如何在后台工作?
【发布时间】:2021-07-17 23:01:30
【问题描述】:

我最近才开始使用 Junit 测试,所以如果我的术语不正确,请原谅。据我所知,如果我们用 @test 注释方法,这些方法将成为测试方法,并且我们可以通过单击旁边的播放按钮使用 IDE(我使用 Intellij)运行它。在后台,它可能会实例化 Test 类的实例并运行选定的方法。我的问题是,在下面的示例中,如果 test1 和 test2 都使用和编辑同一 Test 类实例的相同 hello 字符串,由于 test2 在 test1 之后运行,它应该打印 hello 字符串的编辑版本?即:test2 应该打印“1”。但在这种情况下,它会打印一个空字符串。这是为什么呢?

class Test{
   private  String hello = "";

   @Test
   void test1() {
      hello = hello + "1";
      System.out.println(hello);
   }
   @Test
   void test2() {
      System.out.println(hello)
   }
}

【问题讨论】:

  • “但显然它没有,我在运行 Test 类后只得到“1”。” .... 这个不清楚,第二句话是什么意思?您期望输出“1”,但没有得到 test2,仅在运行整个测试类时,或者您期望来自 test2 的输出不同于“1”,但它打印了“1”? “因为 test2 在 test1 之后运行” 不一定是真的。当您没有明确指定测试订单时,不要依赖测试订单。 Junit 运行它认为合适的测试。

标签: java unit-testing testing junit junit5


【解决方案1】:

这是由于测试的生命周期而发生的。 您猜对了,确实 JUnit 实例化了测试的 Class(在本例中为 class Test)。

换句话说,在 JUnit 的代码中某处有一行: Test test = new Test()(在实际代码中它使用反射,但为了这个问题没关系)。

然后它运行测试方法,到目前为止一切顺利 - 你是对的:

Test test = new Test();

test.test1();

test.test2();
// handle failures, exceptions, etc.

但是,JUnit 的设计方式是在运行每个测试方法之前实例化测试类。这是 JUnit 框架的设计决策。

因此,JUnit 中发生的事情的“更准确”表示如下所示:

Test test = new Test();

test.test1();

....

test = new Test();

test.test2();

这是 JUnit 的默认行为,所有数据字段都会为每个测试一遍又一遍地实例化,它保证 test1 打印 1 test2 打印一个空字符串。

无论实际测试执行的顺序如何,都会发生这种情况。

现在,可以通过在测试类上使用 @TestInstance(LifeCycle.PER_CLASS) 注释来改变这种行为,但它是一个非常高级的东西。它将指示 JUnit 引擎只创建一个 Test 类对象并运行其中的所有测试方法。因此,如果一个测试方法将更改类 Test 中定义的数据字段,则另一个测试实际上会看到这种变化。

如果您有兴趣了解有关 @TestInstance 的更多信息 - 请考虑阅读 this article for example

【讨论】:

    【解决方案2】:

    在大多数情况下,单元测试不应依赖于顺序或执行。

    默认情况下,JUnit 不会保证执行顺序,在这种情况下,test1 可以在 test2 之后或之前执行。

    对于测试,您可以使用@BeforeEach@BeforeAll 在测试之前执行一些代码。

    您也可以使用@Order(1) 来强制执行测试命令。但是,除非在非常具体的情况下,否则我会再次强烈主张它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多