• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.mockitoutil;
2 
3 import org.assertj.core.api.AbstractThrowableAssert;
4 import org.assertj.core.api.Assertions;
5 import org.junit.rules.MethodRule;
6 import org.junit.runners.model.FrameworkMethod;
7 import org.junit.runners.model.Statement;
8 
9 /**
10  * Junit rule for testing exception handling other JUnit rules, like Mockito JUnit rules.
11  * Makes it easy to assert on expected exceptions triggered by the rule under test.
12  */
13 public class SafeJUnitRule implements MethodRule {
14 
15     private final MethodRule testedRule;
16     private FailureAssert failureAssert = null;
17     private Runnable successAssert = new Runnable() { public void run() { } };
18 
19     /**
20      * Wraps rule under test with exception handling so that it is easy to assert on exceptions fired from the tested rule.
21      */
SafeJUnitRule(MethodRule testedRule)22     public SafeJUnitRule(MethodRule testedRule) {
23         this.testedRule = testedRule;
24     }
25 
apply(final Statement base, final FrameworkMethod method, final Object target)26     public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
27         return new Statement() {
28             public void evaluate() throws Throwable {
29                 try {
30                     testedRule.apply(base, method, target).evaluate();
31                     successAssert.run();
32                 } catch (Throwable t) {
33                     if (failureAssert == null) {
34                         throw t;
35                     }
36                     failureAssert.doAssert(t);
37                     return;
38                 }
39                 if (failureAssert != null) {
40                     //looks like the user expects a throwable but it was not thrown!
41                     throw new ExpectedThrowableNotReported("Expected the tested rule to throw an exception but it did not.");
42                 }
43             }
44         };
45     }
46 
47     /**
48      * Expects that _after_ the test, the rule will fire specific exception with specific exception message
49      */
50     public void expectFailure(final Class<? extends Throwable> expected, final String expectedMessage) {
51         this.expectFailure(new FailureAssert() {
52             public void doAssert(Throwable t) {
53                 assertThrowable(t, expected).hasMessage(expectedMessage);
54             }
55         });
56     }
57 
58     /**
59      * Expects that _after_ the test, the rule will fire specific exception with specific exception message
60      */
61     public void expectFailure(final Class<? extends Throwable> expected) {
62         this.expectFailure(new FailureAssert() {
63             public void doAssert(Throwable t) {
64                 assertThrowable(t, expected);
65             }
66         });
67     }
68 
69     private static AbstractThrowableAssert assertThrowable(Throwable throwable, Class<? extends Throwable> expected) {
70         return Assertions.assertThat(throwable).isInstanceOf(expected);
71     }
72 
73     /**
74      * Expects that _after_ the test, the rule will fire an exception
75      */
76     public void expectFailure(FailureAssert failureAssert) {
77         this.failureAssert = failureAssert;
78     }
79 
80     /**
81      * Expects that _after_ the test, given assert will run
82      */
83     public void expectSuccess(Runnable successAssert) {
84         this.successAssert = successAssert;
85     }
86 
87     /**
88      * Offers a way to assert the throwable triggered by the tested rule
89      */
90     public interface FailureAssert {
91         void doAssert(Throwable t);
92     }
93 
94     /**
95      * Thrown when user expects the tested rule to throw an exception but no exception was thrown
96      */
97     class ExpectedThrowableNotReported extends Throwable {
98         public ExpectedThrowableNotReported(String message) {
99             super(message);
100         }
101     }
102 }
103