在任何测试步骤之前调用每个JUnit中的私有方法

时间:2014-07-15 01:34:34

标签: java junit

我想知道在编写JUnit测试时,以下是否存在任何技术差异:

选项1: 定义一个设置方法,即用@Before注释,以在运行任何@Test方法之前初始化测试夹具状态。

选项2: 定义一个私有方法 - 只是一个没有任何注释的普通旧私有方法 - 执行相同的初始化,并使每个@Test方法的第一行调用此方法。 (忽略在每次测试中都有人忘记调用该方法的可能性。我正在寻找技术差异,而不是人为因素)

选项2的示例:

public class MyTest {

    private void runSetupLogic() {
        // whatever @Before method would have done
    }

    @Test
    public void testMethod1() {
        runSetupLogic();
        // test logic
    }

    @Test
    public void testMethod2() {
        runSetupLogic();
        // test logic
    }
}

3 个答案:

答案 0 :(得分:2)

我不相信。
但是,如果您实现了另一个函数,例如 tearDown(),它基本上可以用作 @After 方法,我会认为你可能会这样做好好利用它们的可读性,为了其他合作者甚至自己的利益。

使用 @Before @After 注释的好处是他们避免在每个单元测试开始时调用方法,旨在为您节省额外的维护。如果由于某种原因您忘记将调用添加到 setUp()和/或 tearDown()方法,谁知道哪些内容可能出错。

当然,如果您在每次测试之前需要完全相同的设置。如果您想要为不同的单元测试设置完全不同的设置,那么您可能应该查看正在测试的类的功能,并问自己是否可以模块化更多。

答案 1 :(得分:2)

它们并非真正完全相同,但是对于所有意图和目的,任何一种方式都应该没问题。但是,如果您对技术分析感兴趣,那么我对Github上当前JUnit 4代码的不清楚理解如下:

使用默认的JUnit 4 runner [{3}} @Before时,使用/** * Returns a {@link Statement}: run all non-overridden {@code @Before} * methods on this class and superclasses before running {@code next}; if * any throws an Exception, stop execution and pass the exception on. */ protected Statement withBefores(FrameworkMethod method, Object target, Statement statement) { List<FrameworkMethod> befores = getTestClass().getAnnotatedMethods( Before.class); return befores.isEmpty() ? statement : new RunBefores(statement, befores, target); } 时,似乎是运行的实际代码:

public class RunBefores extends Statement {
    private final Statement next;

    private final Object target;

    private final List<FrameworkMethod> befores;

    public RunBefores(Statement next, List<FrameworkMethod> befores, Object target) {
        this.next = next;
        this.befores = befores;
        this.target = target;
    }

    @Override
    public void evaluate() throws Throwable {
        for (FrameworkMethod before : befores) {
            before.invokeExplosively(target);
        }
        next.evaluate();
    }

以上调用src/main/java/org/junit/runners/BlockJUnit4ClassRunner.java中的RunBefores:

public Object invokeExplosively(final Object target, final Object... params)
        throws Throwable {
    return new ReflectiveCallable() {
        @Override
        protected Object runReflectiveCall() throws Throwable {
            return method.invoke(target, params);
        }
    }.run();
}

invokeExplosively方法定义位于src/main/java/org/junit/internal/runners/statements/RunBefores.java

@Before

似乎使用反射来调用用@Before注释的方法。

无论如何,希望这个答案有点正确,但我不确定。如果有人有任何更正,我可以从评论中编辑它们。顺便提一下,这里引用的是{{1}}注释的javadoc:src/main/java/org/junit/runners/model/FrameworkMethod.java

答案 2 :(得分:1)

好处来自报道。

在您的方法中:runSetupLogic()

从测试开始运行时,在测试中报告。不是设置的一部分,也不是初始化的一部分。

如果设置方法失败,您可以准确描述失败的设置...设置与测试。

before方法允许您将测试失败与设置失败隔离开来,并允许报告解决方案。