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