1 package org.junit.internal.matchers; 2 3 import org.hamcrest.Description; 4 import org.hamcrest.Factory; 5 import org.hamcrest.Matcher; 6 import org.hamcrest.TypeSafeMatcher; 7 8 /** 9 * A matcher that applies a delegate matcher to the cause of the current Throwable, returning the result of that 10 * match. 11 * 12 * @param <T> the type of the throwable being matched 13 */ 14 public class ThrowableCauseMatcher<T extends Throwable> extends 15 TypeSafeMatcher<T> { 16 17 private final Matcher<? extends Throwable> causeMatcher; 18 ThrowableCauseMatcher(Matcher<? extends Throwable> causeMatcher)19 public ThrowableCauseMatcher(Matcher<? extends Throwable> causeMatcher) { 20 this.causeMatcher = causeMatcher; 21 } 22 describeTo(Description description)23 public void describeTo(Description description) { 24 description.appendText("exception with cause "); 25 description.appendDescriptionOf(causeMatcher); 26 } 27 28 @Override matchesSafely(T item)29 protected boolean matchesSafely(T item) { 30 return causeMatcher.matches(item.getCause()); 31 } 32 33 @Override describeMismatchSafely(T item, Description description)34 protected void describeMismatchSafely(T item, Description description) { 35 description.appendText("cause "); 36 causeMatcher.describeMismatch(item.getCause(), description); 37 } 38 39 /** 40 * Returns a matcher that verifies that the outer exception has a cause for which the supplied matcher 41 * evaluates to true. 42 * 43 * @param matcher to apply to the cause of the outer exception 44 * @param <T> type of the outer exception 45 */ 46 @Factory hasCause(final Matcher<? extends Throwable> matcher)47 public static <T extends Throwable> Matcher<T> hasCause(final Matcher<? extends Throwable> matcher) { 48 return new ThrowableCauseMatcher<T>(matcher); 49 } 50 }