setUp/tearDown (@Before/@After) 为什么我们需要它们在 JUnit 中?

2022-08-31 14:21:38

我相信我们都知道 setUp(@Before) 将在任何测试方法之前执行,而 tearDown(@After) 将在测试方法之后执行。

此外,我们知道 Junit 将为每个测试方法创建一个 Test 实例。

我的问题是,我们可以将setUp方法内容移动到类构造函数并删除setUp方法吗?保留设置方法有什么具体原因吗?


答案 1

这篇(旧的)JUnit最佳实践文章是这样说的:

不要使用测试用例构造函数来设置测试用例

在构造函数中设置测试用例不是一个好主意。考虑:

public class SomeTest extends TestCase
   public SomeTest (String testName) {
      super (testName);
      // Perform test set-up
   }
}

想象一下,在执行设置时,设置代码会引发 .作为响应,JUnit 将抛出一个 ,指示无法实例化测试用例。下面是生成的堆栈跟踪的示例:IllegalStateExceptionAssertionFailedError

junit.framework.AssertionFailedError: Cannot instantiate test case: test1   
    at junit.framework.Assert.fail(Assert.java:143)
    at junit.framework.TestSuite.runTest(TestSuite.java:178)
    at junit.framework.TestCase.runBare(TestCase.java:129)
    at junit.framework.TestResult.protect(TestResult.java:100)
    at junit.framework.TestResult.runProtected(TestResult.java:117)
    at junit.framework.TestResult.run(TestResult.java:103)
    at junit.framework.TestCase.run(TestCase.java:120)
    at junit.framework.TestSuite.run(TestSuite.java, Compiled Code)
    at junit.ui.TestRunner2.run(TestRunner.java:429)

这个堆栈跟踪被证明是相当无用的;它仅指示无法实例化测试用例。它没有详细说明原始错误的位置或来源。由于缺乏信息,很难推断出异常的根本原因。

无需在构造函数中设置数据,而是通过重写 来执行测试设置。其中引发的任何异常都会被正确报告。将此堆栈跟踪与前面的示例进行比较:setUp()setUp()

java.lang.IllegalStateException: Oops
    at bp.DTC.setUp(DTC.java:34) 
    at junit.framework.TestCase.runBare(TestCase.java:127)
    at junit.framework.TestResult.protect(TestResult.java:100)
    at junit.framework.TestResult.runProtected(TestResult.java:117)
    at junit.framework.TestResult.run(TestResult.java:103)
    ...

此堆栈跟踪的信息量要大得多。它显示引发哪个异常()以及从哪里抛出。这使得解释测试设置的失败变得更加容易。IllegalStateException


答案 2

在工作中,我们发现了一些相当有趣的东西,可以回答你的问题。当您运行测试套件,尤其是大量测试(200 +)时,JUnit开始使用大量内存。这是因为在运行任何实际的测试方法之前,所有测试都已实例化。

因此,我们遇到了“内存泄漏”。因为我们使用Spring来连接一些JPA EntityManager对象用于我们的数据库测试,这变成了大量的对象和大量的内存,并且在测试的一半左右,我们得到了OutOfMemory异常。

恕我直言,最佳做法是使用 setUp 和 tearDown 来注入依赖项,并清空任何和所有类引用。这将使您的测试运行得更快,并为您节省很多麻烦!

希望您能从我们的错误中吸取教训:)


推荐