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: , , , , ,

3 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 :)

  3. ryan Says:

    the console output shows inner, middle, outer, but as far as I can tell from the api documentation it should show outer, middle, inner.

Leave a Reply

Please note, that no personal information like your IP address is stored and you're not required to enter you real name.

Comments must be approved before they are published, so please be patient after having posted a comment - it might take a short while.

Please leave these two fields as-is:
Search
Categories