I want to write an JUnit @Rule (version 4.10) to setup some objects (an Entity Manager) and make them available in the test, by "injecting" it into an variable.
Something like this:
public class MyTestClass() {
@Rule
MyEntityManagerInjectRule = new MyEntityManagerInjectRule():
//MyEntityManagerInjectRule "inject" the entity manager
EntityManger em;
@Test...
}
The Problem is that I do not know how to get the current instance of MyTestClass
in the MyEntityManagerInjectRule (extends TestRule), because it has only one method.
Statement apply(Statement base, Description description);
Within Description there is only the class MyTestClass but not the instance used for the test.
An alternative would be using org.junit.rules.MethodRule but this is deprecated. Before and After are not sufficient for this task, because then I would need to copy the code to the tests, and they are more or less deprecated too. (See Block4JClassRunner.withBefores / withAfters).
So my question in how could I access the test class instance without using deprecated stuff.
Annotation Type ClassRule. @Retention(value=RUNTIME) @Target(value={FIELD,METHOD}) public @interface ClassRule. Annotates static fields that reference rules or methods that return them. A field must be public, static, and a subtype of TestRule . A method must be public static, and return a subtype of TestRule .
ADVERTISEMENT. To use the JUnit rules, we need to add the @Rule annotation in the test. @Rule: It annotates the fields. It refer to the rules or methods that returns a rule. The annotated fields must be public, non-static, and subtypes of the TestRule or MethodRule.
To write a custom rule, we need to implement the TestRule interface. As we can see, the TestRule interface contains one method called apply(Statement, Description) that we must override to return an instance of Statement. The statement represents our tests within the JUnit runtime.
A JUnit 4 rule is a component that intercepts test method calls and allows us to do something before a test method is run and after a test method has been run. All JUnit 4 rule classes must implement the org. junit.
The proper way to achieve that is to make your rule implement org.junit.rules.MethodRule
(not TestRule
). The apply()
method of the MethodRule
interface has a target
argument, which holds a reference to the current instance of the test class (of course, it is a different instance each time a method is executed).
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()");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With