JUnit uses TestRule
objects to alter the behavior of test method. JUnit uses @Rule
and @ClassRule
annotation to determine the test rules defined.
A test rule can be applied either before each test method or once at the class level depending on whether you have defined the test rule using @Rule
or @ClassRule
. Multiple TestRule
s can be applied where each rule modifies an existing statement and returns a new statement thereby bringing the necessary change which in turn is passed to the next test rule. A test rule can be defined either using a field that is a subtype of TestRule
or method that returns subtype of TestRule
. If a test rule is applied using @Rule
, the field or method must be public and non-static.
In the below test class we have defined multiple test rules. There are couple of field level test rules rule1
and rule2
, and couple of methods that return TestRule
instance.
MultipleTestRulesExample:
package com.javarticles.junit; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; public class MultipleTestRulesExample { @Rule public final TestRule rule1 = new TestRule() { public Statement apply(Statement base, Description description) { System.out.println("apply field rule1"); return base; } }; @Rule public final TestRule rule2 = new TestRule() { public Statement apply(Statement base, Description description) { System.out.println("apply field rule2"); return base; } }; @Rule public TestRule rule1() { return new TestRule() { public Statement apply(Statement base, Description description) { System.out.println("apply method rule1"); return base; } }; } @Rule public TestRule rule2() { return new TestRule() { public Statement apply(Statement base, Description description) { System.out.println("apply method rule2"); return base; } }; } @BeforeClass public static void beforeClass() throws Exception { System.out.println("Before class"); } @Before public void beforeTest() throws Exception { System.out.println("Before test"); } @Test public void test1() { System.out.println("test1"); } @Test public void test2() { System.out.println("test2"); } @After public void afterTest() throws Exception { System.out.println("After test"); } @AfterClass public static void afterClass() throws Exception { System.out.println("After class"); } }
You can see from the output the test rules are applied just before calling the @Before
annotated test method. The test rules are applied for each test method.
Output:
Before class apply method rule1 apply method rule2 apply field rule1 apply field rule2 Before test test1 After test apply method rule1 apply method rule2 apply field rule1 apply field rule2 Before test test2 After test After class
Field TestRule vs Method TestRule
If you notice in the above test class there are multiple annotated @Rule
s and we have rules that are defined as fields as well as methods. In such cases the rules defined by methods will be applied first followed by rules defined by fields.
Output:
Before class apply method rule1 apply method rule2 apply field rule1 apply field rule2 Before test test1 After test apply method rule1 apply method rule2 apply field rule1 apply field rule2 Before test test2 After test After class
Download the source code
This was an example about TestRules defined using @Rule
annotation.