为什么 jUnit 的 fixtureSetup 必须是静态的? [英] Why must jUnit's fixtureSetup be static?

查看:20
本文介绍了为什么 jUnit 的 fixtureSetup 必须是静态的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用 jUnit 的 @BeforeClass 注释标记了一个方法,并得到这个异常,说它必须是静态的.理由是什么?这迫使我所有的初始化都在静态字段上,据我所知没有充分的理由.

I marked a method with jUnit's @BeforeClass annotation, and got this exception saying it must be static. What's the rationale? This forces all my init to be on static fields, for no good reason as far as I see.

在 .Net (NUnit) 中,情况并非如此.

In .Net (NUnit), this is not the case.

编辑 - 用@BeforeClass 注释的方法只运行一次这一事实与它是静态方法无关 - 一个非静态方法只能运行一次(如在 NUnit 中)).

Edit - the fact that a method annotated with @BeforeClass runs only once has nothing to do with it being a static method - one can have a non-static method run only once (as in NUnit).

推荐答案

JUnit 总是 为每个 @Test 方法创建一个测试类实例.这是一个基本的设计决策,目的是让编写没有副作用的测试更容易.好的测试没有任何运行顺序依赖性(参见 FIRST)和为每个测试创建测试类的新实例及其实例变量对于实现这一点至关重要.一些测试框架对所有测试重用相同的测试类实例,这导致在测试之间意外产生副作用的可能性更大.

JUnit always creates one instance of the test class for each @Test method. This is a fundamental design decision to make it easier to write tests without side-effects. Good tests do not have any order-of-run dependencies (see F.I.R.S.T) and creating fresh instances of the test class and its instance variables for each test is crucial in achieving this. Some testing frameworks reuse the same test class instance for all tests, which leads to more possibilities of accidentally creating side-effects between tests.

而且因为每个测试方法都有自己的实例,所以@BeforeClass/@AfterClass 方法作为实例方法是没有意义的.否则,应该在哪个测试类实例上调用方法?如果@BeforeClass/@AfterClass 方法可以引用实例变量,那么只有一个@Test 方法可以访问这些相同的实例变量 - 其余的实例变量将位于它们的默认值 - 并且 @Test 方法将被随机选择,因为 .class 文件中方法的顺序是未指定的/依赖于编译器(IIRC,Java 的反射 API 返回方法的顺序与它们在 .class 文件中声明的顺序相同).class 文件,尽管该行为未指定 - 我已经编写了一个库,用于按行号对它们进行实际排序).

And because each test method has its own instance, it makes no sense for the @BeforeClass/@AfterClass methods to be instance methods. Otherwise, on which of the test class instances should the methods be called? If it would be possible for the @BeforeClass/@AfterClass methods to reference instance variables, then only one of the @Test methods would have access to those same instance variables - the rest would have the instance variables at their default values - and the @Test method would be randomly selected, because the order of methods in the .class file is unspecified/compiler-dependent (IIRC, Java's reflection API returns the methods in the same order as they are declared in the .class file, although also that behaviour is unspecified - I have written a library for actually sorting them by their line numbers).

因此将这些方法强制为静态是唯一合理的解决方案.

So enforcing those methods to be static is the only reasonable solution.

这是一个例子:

public class ExampleTest {

    @BeforeClass
    public static void beforeClass() {
        System.out.println("beforeClass");
    }

    @AfterClass
    public static void afterClass() {
        System.out.println("afterClass");
    }

    @Before
    public void before() {
        System.out.println(this + "	before");
    }

    @After
    public void after() {
        System.out.println(this + "	after");
    }

    @Test
    public void test1() {
        System.out.println(this + "	test1");
    }

    @Test
    public void test2() {
        System.out.println(this + "	test2");
    }

    @Test
    public void test3() {
        System.out.println(this + "	test3");
    }
}

打印:

beforeClass
ExampleTest@3358fd70    before
ExampleTest@3358fd70    test1
ExampleTest@3358fd70    after
ExampleTest@6293068a    before
ExampleTest@6293068a    test2
ExampleTest@6293068a    after
ExampleTest@22928095    before
ExampleTest@22928095    test3
ExampleTest@22928095    after
afterClass

如您所见,每个测试都使用自己的实例执行.JUnit 所做的与此基本相同:

As you can see, each of the tests is executed with its own instance. What JUnit does is basically the same as this:

ExampleTest.beforeClass();

ExampleTest t1 = new ExampleTest();
t1.before();
t1.test1();
t1.after();

ExampleTest t2 = new ExampleTest();
t2.before();
t2.test2();
t2.after();

ExampleTest t3 = new ExampleTest();
t3.before();
t3.test3();
t3.after();

ExampleTest.afterClass();

这篇关于为什么 jUnit 的 fixtureSetup 必须是静态的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆