JUnit:在调用每个@Test方法之前的新实例。有什么好处?

时间:2012-12-23 10:28:29

标签: java unit-testing testing junit instance

目前,我正在阅读“JUnit in action”一书。在本书中,我发现了以下文字:

  

JUnit在调用每个测试类之前创建一个新的测试类实例   @测试方法。这有助于提供测试方法之间的独立性   避免测试代码中的无意的副作用。因为每次测试   方法在新的测试类实例上运行,我们不能重用实例   测试方法中的变量值。

现在我认为这种方法没有多大意义:

例如:

public class CalculatorTest {
    @Test
    public void testAdd_1() {
        Calculator calculator = new Calculator();
        double result = calculator.add(1, 1);
        assertEquals(2, result, 0);
    }

    @Test
    public void testAdd_2() {
        Calculator calculator = new Calculator();
        double result = calculator.add(2, 2);
        assertEquals(4, result, 0);
    }
}

对于测试类CalculatorTest,没有任何好处。

好的,让我们继续关注另一个例子:

public class OneTest {

    static byte count;

    public OneTest() {
        count++;
    }

    @Test
    public void test1() {
        System.out.println(count);
    }

    @Test
    public void test2() {
        System.out.println(count);
    }
}

对于测试类OneTest,我找到了一种方法,可以为许多测试方法使用相同的变量计数......

那么,如何看待书中描述的方法的真正好处呢?

3 个答案:

答案 0 :(得分:16)

  

如何看待本书中描述的方法的真正好处?

单独实例的目的不是为了任何好处,而是为了维护合同,即每个测试应该独立执行,而不会影响先前测试的执行。除了为每个测试使用不同的实例之外,没有其他方法可以确保此合同。

例如,Spring事务管理确保在默认情况下通过测试回滚对数据库所做的所有更改,以维持相同的合同。

因此,通常不鼓励在测试中使用静态变量,因为它会破坏每个测试的一个实例的整个目的,以便为每个测试提供一个清晰的平板。

答案 1 :(得分:15)

在测试方法之间保持状态清洁对于单元测试很有用,但却妨碍了功能测试,其中通常需要在测试之间存在依赖关系(例如,当您使用Selenium测试网页时,不用打扰它是有用的如果登录页面的测试失败,则运行某个页面的测试。)

这是我创建TestNG的主要原因之一,{{3}}没有在每个方法之间实例化一个新类,因此您可以选择而不是将此决定强加给您。

TestNG还支持测试的依赖性,多线程测试,具有组的概念(“仅运行servlet测试”)和更多功能。

答案 2 :(得分:2)

如果您正在测试一个可变类,那么在每个测试方法的开头让测试对象处于已知状态是非常有价值的,因此测试执行的顺序无关紧要。最简单的方法是为每个测试创建该类的新实例,并避免使用静态字段。

在您的计算器示例中,您的Calculator类似乎是不可变的,方法调用的结果仅取决于参数。因此,一项测试影响另一项测试的风险就不存在了。

我不太清楚你的第二个例子。您编写的注释为@Test的方法使用共享的静态字段,但您的方法没有断言,并且没有真正测试任何东西。

如果你想使用静态字段或者确实要保留和重用被测试类的单个实例,那么肯定可以这样做,但是为了让你的测试工作并保持彼此独立,往往需要更加关心。