Ordering your JUnit Rules using a RuleChain

February 21st, 2012 by

JUnit Rules are a handy solution if one needs to alter test methods or wants to share common functionality between several test cases. JUnit 4.10 introduced a new class to order several rules according to our needs using a so called rule-chain.

In the following example, we’re going to create a simple custom rule and afterwards bind several instances of it in a specified order to a test method.

 

Adding JUnit

Just one Maven dependency needed here – JUnit 4.10

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.10</version>
    <scope>test</scope>
</dependency>

Rule definition

Now we need to define a role – as you might remember a role consists of an annotation (that’s what is used in the test case) and and implementation class that implements TestRule.

We’re going a simple rule that adds some console logging to our test methods – it takes a note as constructor string argument and prints it when the rule is applied later.

package com.hascode.tutorial;
 
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
 
public class ConsoleOutRule implements TestRule {
 private final String note;
 
 public ConsoleOutRule(final String note) {
 this.note = note;
 }
 
 public Statement apply(final Statement base, final Description description) {
 System.out.println("rule applied. note: " + note);
 return base;
 }
}

Applying the Rule to a Test Case

If we wanted to modify a test with our new rule, this could be a scenario

package com.hascode.tutorial;
 
import static org.junit.Assert.assertTrue;
 
import org.junit.Rule;
import org.junit.Test;
 
public class SomeUnitTest {
 @Rule
 public ConsoleOutRule rule = new ConsoleOutRule("somewhere");
 
 @Test
 public void testSomeMethod() {
 System.out.println("test started");
 assertTrue(true);
 }
}

Running the test would produce the following output:

rule applied. note: somewhere
test started

Ordering Rules using RuleChain

Finally we’re wrapping several rules using RuleChain’s static builder methods

package com.hascode.tutorial;
 
import static org.junit.Assert.assertTrue;
 
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.rules.TestRule;
 
public class SomeUnitTestWithRuleChain {
 @Rule
 public TestRule chain = RuleChain.outerRule(new ConsoleOutRule("outer"))
 .around(new ConsoleOutRule("middle"))
 .around(new ConsoleOutRule("inner"));
 
 @Test
 public void testSomeMethod() {
 System.out.println("test started");
 assertTrue(true);
 }
}

The following output is produced

rule applied. note: inner
rule applied. note: middle
rule applied. note: outer
test started

Tutorial Sources

I have put the source from this tutorial on my Bitbucket repository – download it there or check it out using Mercurial:

hg clone https://bitbucket.org/hascode/junit-rule-chaining-samples

Resources

Tags: , , , , ,

2 Responses to “Ordering your JUnit Rules using a RuleChain”

  1. John Says:

    Where did you see that a rule needs a corresponding annotation? Removing @ConsoleOut bares the same result.

  2. micha kops Says:

    geesh thanks for mentioning .. these were fragments of a first approach where I would have read data from the annotation used in the rule implementation. i’ve updated the article! damn nightly builds :)

Leave a Reply

Please leave these two fields as-is:

Protected by Invisible Defender. Showed 403 to 81,008 bad guys.

Search
Categories