我正在尝试使用JUnit创建测试自动化套件。对于所有测试,我想创建一个规则,为此我创建了一个接口并将规则放在其中。我想要运行的任何测试都必须实现该接口。它没有抛出任何编译器错误,但是,当我的Test类实现该接口时,这似乎不起作用。 以下是我创建的界面。
public interface IBaseTest {
@Rule
public TestRule test = new TestWatcher(){
@Override
protected void starting(Description description)
{
System.out.println("Starting Test: " + description);
}
};
}
或者,我可以创建上面的类并从该类扩展我的所有测试类,我尝试了它并且它工作得很好,但是这会阻止我从任何其他类扩展我的测试方法。
有没有办法让我创建适用于我所有测试的规则而不从基类扩展?
答案 0 :(得分: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 {
}
}