3

我正在尝试使用 JUnit 创建测试自动化套件。对于所有测试,我想创建一个规则,为此我创建了一个接口并将规则放入其中。我想运行的任何测试都必须实现该接口。它没有引发任何编译器错误,但是,当我的 Test 类实现该接口时,这似乎不起作用。以下是我创建的界面。

public interface IBaseTest {
    @Rule
    public TestRule test = new TestWatcher(){
        @Override
        protected void starting(Description description)
        {
            System.out.println("Starting Test: " + description);
        }
    };
}

或者,我可以将上面的内容创建为一个类并从该类扩展我的所有测试类,我尝试了它并且它工作得很好,但这会阻止我从任何其他类扩展我的测试方法。

有没有办法让我创建适用于我所有测试的规则,而无需从基类扩展?

4

1 回答 1

1

是的,我知道有一种方法,但它会让你编写一些额外的代码。

首先,JUnit 忽略您的 TestRule 的原因是因为它是在接口上声明的,因此是静态的(和最终的)。

为了克服这个问题,需要编写一个这样的自定义运行器:

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

import org.junit.Rule;
import org.junit.rules.TestRule;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.InitializationError;

public final class MyRunner extends BlockJUnit4ClassRunner {

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

    @Override
    protected List<TestRule> getTestRules(Object target) {
        List<TestRule> testRules = super.getTestRules(target);
        testRules.addAll(getStaticFieldTestRules(target));
        return testRules;
    }

    private List<TestRule> getStaticFieldTestRules(Object target) {
        List<TestRule> testRules = new ArrayList<>();
        Class<?> clazz = target.getClass();
        for (Field f : clazz.getFields()) {
            if ((f.getModifiers() & Modifier.STATIC) != 0) {
                if (f.isAnnotationPresent(Rule.class)) {
                    try {
                        testRules.add((TestRule) f.get(target));
                    } catch (IllegalArgumentException | IllegalAccessException e) {
                        throw new IllegalStateException(e);
                    }
                }
            }
        }
        return testRules;
    }
}

最后,注释您的测试类以使用新的自定义运行程序运行,一切都如您所愿......

import org.junit.runner.RunWith;

@RunWith(MyRunner.class)
public class Test implements IBaseTest {

    @org.junit.Test
    public void testName1() throws Exception {
    }

    @org.junit.Test
    public void testName2() throws Exception {

    }

}
于 2014-08-03T08:26:24.980 回答