25

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

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

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

例如:

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,我找到了一种对许多测试方法使用相同变量计数的方法......

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

4

3 回答 3

20

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

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

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

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

于 2012-12-23T12:17:42.650 回答
18

保持测试方法之间的状态清洁对单元测试很有用,但会妨碍功能测试,因为测试之间通常需要依赖关系(例如,当您使用 Selenium 测试网页时,不必费心运行如果登录页面的测试失败,则返回某个页面)。

这是我创建TestNG的主要原因之一,它不会在每个方法之间实例化一个新类,因此给你选择而不是把这个决定强加给你。

TestNG 还支持测试的依赖关系、多线程测试、组的概念(“仅运行 servlet 测试”)以及更多功能。

于 2012-12-24T06:45:18.260 回答
3

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

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

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

如果您想使用静态字段或确实保留并重用被测类的单个实例,当然可以这样做,但要使您的测试工作并保持彼此独立往往需要更多的关注。

于 2012-12-23T16:25:03.000 回答