我想编写一个JUnit @Rule(版本4.10)来设置一些对象(一个实体管理器),并通过将它“注入”变量使它们在测试中可用。
这样的事情:
public class MyTestClass() {
@Rule
MyEntityManagerInjectRule = new MyEntityManagerInjectRule():
//MyEntityManagerInjectRule "inject" the entity manager
EntityManger em;
@Test...
}
问题是我不知道如何在MyEntityManagerInjectRule(扩展TestRule)中获取MyTestClass
的当前实例,因为它只有一个方法。
Statement apply(Statement base, Description description);
在Description中只有MyTestClass类,但没有用于测试的实例。
另一种方法是使用org.junit.rules.MethodRule但不推荐使用。 之前和之后不足以完成此任务,因为那时我需要将代码复制到测试中,并且它们或多或少都被弃用了。 (参见Block4JClassRunner.withBefores / withAfters)。
所以我的问题是如何在不使用弃用的东西的情况下访问测试类实例。
答案 0 :(得分:16)
实现这一目标的正确方法是使您的规则实施org.junit.rules.MethodRule
(而不是TestRule
)。 apply()
接口的MethodRule
方法有一个target
参数,包含对测试类的当前实例的引用(当然,它是一个每次执行方法时都有不同的实例。)
MethodRule
public class ExampleMethodRule implements MethodRule {
@Override
public Statement apply(final Statement base,
FrameworkMethod method, Object target) {
System.out.println("ExampleMethodRule#apply()" +
"\n\t base: " + base +
"\n\t method (current test method): " + method +
"\n\t target (current test class instance): "+target);
return new Statement() {
@Override
public void evaluate() throws Throwable {
System.out.println("->before evaluate()");
try {
base.evaluate();
} finally {
System.out.println("->after evaluate()");
}
}
};
}
}
@Rule
public class ExampleTest {
@Rule
public ExampleMethodRule exampleMethodRule = new ExampleMethodRule();
@BeforeClass
public static void beforeClass() {
System.out.println("@BeforeClass");
}
@AfterClass
public static void afterClass() {
System.out.println("@AfterClass");
}
@Before
public void before() {
System.out.println("@Before");
}
@After
public void after() {
System.out.println("@After");
}
@Test
public void aa() {
System.out.println("method aa()");
}
@Test
public void bb() {
System.out.println("method bb()");
}
}
答案 1 :(得分:12)
怎么样:
public class MyTestClass() {
@Rule
public TestRule MyEntityManagerInjectRule =
new MyEntityManagerInjectRule(this); // pass instance to constructor
//MyEntityManagerInjectRule "inject" the entity manager
EntityManger em;
@Test...
}
只需将测试类实例添加到@Rule
的构造函数中即可。请注意分配顺序。
答案 2 :(得分:4)
有一种不同的方法:规则提供EntityManager而不是注入它。
public class MyTestClass() {
@Rule
public MyEntityManagerRule rule = new MyEntityManagerRule();
@Test
public void firstTest() {
doSomethingWith(rule.getEntityManager());
}
}