使用和不使用挂钩之前/之后运行JUnit测试

时间:2014-11-27 11:32:50

标签: java junit

我有一种情况需要能够在2种不同的“模式”下运行一套JUnit测试:

  • 使用第一种模式,使用@Before@After注释/方法;但是...
  • 使用第二种模式时,请勿使用这些注释/方法,而是运行相同的@Test方法

例如:

public class WidgetTest {
    @Before
    void start() {
        // Do some start up work.
    }

    @After
    void stop() {
        // Do some shutdown work.
    }

    @Test
    public void testWidget() {
        // Given/When/Then, etc.
    }
}

在“模式#1”中,我希望@Before@After方法(分别为start()stop())在testWidget()之前/之后执行。但在“模式#2”中,我希望触发testWidget()方法。

我能想到的最好的是:

public class WidgetTest {
    private boolean useHooks;

    // Ctor, getter and setter for 'useHooks'.

    @Before
    void start() {
        if(useHooks) {
            // Do some start up work.
        }
    }

    @After
    void stop() {
        if(useHooks) {
            // Do some shutdown work.
        }
    }

    @Test
    public void testWidget() {
        // Given/When/Then, etc.
    }
}

但是这会带来一个额外的问题:如何将useHooks注入我的测试套件?它也有点hacky,我想我希望JUnit支持这个开箱即用的用例。

有没有办法实现这个目标?如果是这样,怎么样?

3 个答案:

答案 0 :(得分:1)

查看@Category注释

答案 1 :(得分:1)

我建议考虑这个解决方案:

  • 编写自定义JUnit runner
  • 添加VM参数以在2种所需模式之间切换

以下是我提出的自定义选手的代码:

import java.util.Collections;
import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.internal.runners.statements.RunAfters;
import org.junit.internal.runners.statements.RunBefores;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;

public class MyJUnitRunner extends BlockJUnit4ClassRunner {

    private final boolean runBeforesAndAfters = System.getProperty("run-befores-and-afters") != null;

    public MyJUnitRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected Statement withBefores(FrameworkMethod method, Object target, Statement statement) {
        List<FrameworkMethod> befores = Collections.EMPTY_LIST;
        if (runBeforesAndAfters) {
            befores = getTestClass().getAnnotatedMethods(Before.class);
        }
        return befores.isEmpty() ? statement : new RunBefores(statement, befores, target);
    }

    @Override
    protected Statement withAfters(FrameworkMethod method, Object target, Statement statement) {
        List<FrameworkMethod> afters = Collections.EMPTY_LIST;
        if (runBeforesAndAfters) {
            afters = getTestClass().getAnnotatedMethods(After.class);
        }
        return afters.isEmpty() ? statement : new RunAfters(statement, afters, target);
    }

}

只需添加此选项即可启动JUnits VM:-Drun-befores-and-afters并使用@RunWith(MyJUnitRunner.class)注释您的测试类,然后就完成了。

答案 2 :(得分:1)

您要找的是Parameterized tests,因此您的代码将如下所示(未经过测试)

@RunWith(Parameterized.class)
public class WidgetTest {
    @Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[] {true, false});
    }

    private boolean useHooks

    public WidgetTest(booelan useHooks) {
        this.useHooks = useHooks;
    }
    ....
}