1 /** 2 * 3 */ 4 package org.junit.rules; 5 6 import java.util.ArrayList; 7 import java.util.Collections; 8 import java.util.List; 9 10 import org.junit.runner.Description; 11 import org.junit.runners.model.Statement; 12 13 /** 14 * The RuleChain rule allows ordering of TestRules. You create a 15 * {@code RuleChain} with {@link #outerRule(TestRule)} and subsequent calls of 16 * {@link #around(TestRule)}: 17 * 18 * <pre> 19 * public static class UseRuleChain { 20 * @Rule 21 * public TestRule chain= RuleChain 22 * .outerRule(new LoggingRule("outer rule") 23 * .around(new LoggingRule("middle rule") 24 * .around(new LoggingRule("inner rule"); 25 * 26 * @Test 27 * public void example() { 28 * assertTrue(true); 29 * } 30 * } 31 * </pre> 32 * 33 * writes the log 34 * 35 * <pre> 36 * starting outer rule 37 * starting middle rule 38 * starting inner rule 39 * finished inner rule 40 * finished middle rule 41 * finished outer rule 42 * </pre> 43 */ 44 public class RuleChain implements TestRule { 45 private static final RuleChain EMPTY_CHAIN= new RuleChain( 46 Collections.<TestRule> emptyList()); 47 48 private List<TestRule> rulesStartingWithInnerMost; 49 50 /** 51 * Returns a {@code RuleChain} without a {@link TestRule}. This method may 52 * be the starting point of a {@code RuleChain}. 53 * 54 * @return a {@code RuleChain} without a {@link TestRule}. 55 */ emptyRuleChain()56 public static RuleChain emptyRuleChain() { 57 return EMPTY_CHAIN; 58 } 59 60 /** 61 * Returns a {@code RuleChain} with a single {@link TestRule}. This method 62 * is the usual starting point of a {@code RuleChain}. 63 * 64 * @param outerRule 65 * the outer rule of the {@code RuleChain}. 66 * @return a {@code RuleChain} with a single {@link TestRule}. 67 */ outerRule(TestRule outerRule)68 public static RuleChain outerRule(TestRule outerRule) { 69 return emptyRuleChain().around(outerRule); 70 } 71 RuleChain(List<TestRule> rules)72 private RuleChain(List<TestRule> rules) { 73 this.rulesStartingWithInnerMost= rules; 74 } 75 76 /** 77 * Create a new {@code RuleChain}, which encloses the {@code nextRule} with 78 * the rules of the current {@code RuleChain}. 79 * 80 * @param enclosedRule 81 * the rule to enclose. 82 * @return a new {@code RuleChain}. 83 */ around(TestRule enclosedRule)84 public RuleChain around(TestRule enclosedRule) { 85 List<TestRule> rulesOfNewChain= new ArrayList<TestRule>(); 86 rulesOfNewChain.add(enclosedRule); 87 rulesOfNewChain.addAll(rulesStartingWithInnerMost); 88 return new RuleChain(rulesOfNewChain); 89 } 90 91 /** 92 * {@inheritDoc} 93 */ apply(Statement base, Description description)94 public Statement apply(Statement base, Description description) { 95 for (TestRule each : rulesStartingWithInnerMost) 96 base= each.apply(base, description); 97 return base; 98 } 99 }