代码之家  ›  专栏  ›  技术社区  ›  mhshams

设置/拆卸(@Before/@After)为什么我们需要在JUnit中使用它们?

  •  59
  • mhshams  · 技术社区  · 14 年前

    我们还知道Junit将创建一个Test实例 按试验方法 .

    我的问题是,我们能不能把安装方法的内容移到类构造函数中,然后删除安装方法?是否有任何特定的理由保留设置方法?

    6 回复  |  直到 14 年前
        1
  •  59
  •   Pascal Thivent    14 年前

    JUnit best practices 文章这样说:

    在中设置测试用例

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

    想象一下在表演 设置,设置代码抛出 IllegalStateException . 作为回应, 朱尼特会扔一个 AssertionFailedError ,表示 实例化。下面是一个 生成的堆栈跟踪:

    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() 扔进 设置() 在前面的例子中:

    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)
        ...
    

    这个堆栈跟踪要多得多 被抛出( 非法状态例外 从哪里来的。这就容易多了

        2
  •  26
  •   BjornS    14 年前

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

    因此我们遇到了“内存泄漏”,因为我们使用Spring连接了一些JPA EntiryManager对象来进行数据库测试,这变成了大量的对象和大量的内存,在测试进行到一半的时候,我们得到了内存异常。

        3
  •  23
  •   Community Mr_and_Mrs_D    4 年前

    以下是三个很好的理由。总而言之:

    1. 就在之前 测试用例执行。

    2. 如果安装程序代码在setup()中失败,而不是在构造函数中失败,则可以获得更好的诊断。

    1推迟到测试用例之前设置夹具

    可用性设计
    http://www.artima.com/weblogs/viewpost.jsp?thread=70189

    ... 正如Elliotte Rusty Harold所说,如果要为每个测试方法创建一个新的TestCase实例, “他妈的为什么要用setUp()方法?” 您可以只使用TestCase构造函数。

    我听布鲁斯·埃克尔说过 一个细微的差别 在setUp()中创建fixture与在TestCase构造函数中创建fixture之间。朱尼特 预先创建所有测试用例实例 ,和 然后对每个实例调用setup()、test方法和tearDown() 细微的区别在于构造函数都是在批处理之前调用的,而setUp()方法则是在每个测试方法之前调用的

    2推迟设置夹具,直到所有测试用例都实例化之后


    http://etutorials.org/Programming/Java+extreme+programming/Chapter+4.+JUnit/4.6+Set+Up+and+Tear+Down/

    您可能想知道为什么应该编写setUp()方法,而不是简单地初始化测试用例构造函数中的字段 . 毕竟,因为测试用例的新实例是为它的每个测试方法创建的,所以构造函数总是在setUp()之前被调用。在绝大多数情况下,可以使用构造函数而不是setUp(),而不会产生任何副作用。

    如果您的测试用例是更深层继承层次结构的一部分,您可能希望推迟对象初始化,直到派生的[test]类的实例被完全构造 对于文档来说也是很好的,因为它可以使代码更易于阅读

    三。设置失败时更好的诊断

    JUnit最佳实践(JavaWorld)
    http://www.javaworld.com/jw-12-2000/jw-1221-junit.html

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

    想象一下[在测试用例构造函数中完成安装的代码中]在执行安装时,安装代码抛出一个IllegalStateException。作为响应,JUnit将抛出一个AssertionFailedError,表示测试用例无法实例化。。。

    这个堆栈跟踪[在测试用例构造函数的设置代码中抛出的异常]被证明是相当不具信息性的;它只表明测试用例不能被实例化。

    通过重写setup()执行测试设置。setUp()中引发的任何异常都会正确报告。 ...

    这个堆栈跟踪[在setUp()方法而不是测试用例构造函数中抛出的异常]的信息要丰富得多;它显示了抛出的异常(IllegalStateException)和从何处抛出的异常。 这样就更容易解释测试设置的失败。

        4
  •  6
  •   RichN    14 年前

    自定义跑步者,如 SpringJUnit4ClassRunner @Before 方法。在这种情况下,运行程序可能会注入 @之前 方法需要。但是依赖注入只能在构造对象之后运行。

        5
  •  3
  •   abaghel    7 年前

    假设您的测试类包装,比如说数据库访问。在每次测试之后,您都希望删除测试对数据库所做的任何更改—如果您没有这样做,则每个测试都会针对一个稍微修改过的数据库运行。此外,如果先前测试的某个子集失败,任何给定的测试都可能会看到一组不同的更改。例如,假设test1执行了一个insert,test2检查您是否准确地读取了表的大小。第1天,test1失败,0正确。第二天,test1成功,1是正确的吗?

    顺便说一句,junit还支持 @BeforeClass 如果你想做一个全局设置,设置和拆卸是可选的。

        6
  •  -4
  •   Peter Fine    12 年前

    我认为应该有如下原因:

    1. 如果您将@Before内容移动到构造函数中,这很好,但是@After内容将移动到哪里呢?
    2. Constructor和@Before/@After的区别在于,Constructor应该用来为类实例一些,@Before/@After是用来准备测试用例资源的。