繁体   English   中英

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

[英]Calling a private method inside every JUnit before any test steps

我想知道在编写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
    }
}

我不相信。
但是,如果您要实现另一个函数,例如tearDown() ,则该函数实际上将用作@After方法,我认为您最好将它们用于可读性,以使其他协作者甚至您自己受益。

使用@Before@After注释的好处是,它们避免在每次单元测试开始时都必须调用方法,这是为了节省您的额外维护。 如果由于某种原因您忘记将调用添加到setUp()和/或tearDown()方法中,谁知道会出问题。

当然,这是在每次测试之前都需要完全相同的设置。 如果您打算为完全不同的单元测试设置完全不同的设置,那么也许您应该查看所测试类的功能,并问自己是否可以进一步模块化。

它们实际上并不完全相同 ,但是无论从哪方面来看,任何一种方法都应该是正确的。 但是,如果您对技术分析感兴趣,那么我对Github上当前的JUnit 4代码的理解就会有些不稳定:

这是当您使用@Before使用默认的JUnit 4运行程序src / main / java / org / junit / runners / BlockJUnit4ClassRunner.java时,似乎正在运行的实际代码:

/**
 * 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);
}

上面在src / main / java / org / junit / internal / runners / statements / RunBefores.java中调用RunBefores

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();
    }

invokeExplosively方法定义位于src / main / java / org / junit / runners / model / FrameworkMethod.java中

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();
}

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

无论如何,希望这个答案是正确的,但是我不确定。 如果任何人有任何更正,我可以从注释中对其进行编辑。 顺便说一句,这里提供@Before注释的Javadoc: http : @Before

好处来自于报告。

在您的方法中:runSetupLogic()

从测试开始运行时,将在测试内报告。 不作为设置的一部分,也不作为初始化的一部分。

如果安装方法失败,您将准确了解失败的原因...安装与测试。

使用before方法,您可以将测试失败与设置失败隔离开来,并使报告解决方案也可以知道。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM