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