Skip to content

Commit

Permalink
Merge pull request junit-team#982 from pettermahlen/cause-matcher-typ…
Browse files Browse the repository at this point in the history
…e-variance

Less restrictive type bounds for ThrowableCauseMatcher
  • Loading branch information
kcooney committed Sep 9, 2014
2 parents 533dbb7 + 56a63f1 commit 71a3221
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,46 @@
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

/**
* A matcher that applies a delegate matcher to the cause of the current Throwable, returning the result of that
* match.
*
* @param <T> the type of the throwable being matched
*/
public class ThrowableCauseMatcher<T extends Throwable> extends
TypeSafeMatcher<T> {

private final Matcher<T> matcher;
private final Matcher<? extends Throwable> causeMatcher;

public ThrowableCauseMatcher(Matcher<T> matcher) {
this.matcher = matcher;
public ThrowableCauseMatcher(Matcher<? extends Throwable> causeMatcher) {
this.causeMatcher = causeMatcher;
}

public void describeTo(Description description) {
description.appendText("exception with cause ");
description.appendDescriptionOf(matcher);
description.appendDescriptionOf(causeMatcher);
}

@Override
protected boolean matchesSafely(T item) {
return matcher.matches(item.getCause());
return causeMatcher.matches(item.getCause());
}

@Override
protected void describeMismatchSafely(T item, Description description) {
description.appendText("cause ");
matcher.describeMismatch(item.getCause(), description);
causeMatcher.describeMismatch(item.getCause(), description);
}

/**
* Returns a matcher that verifies that the outer exception has a cause for which the supplied matcher
* evaluates to true.
*
* @param matcher to apply to the cause of the outer exception
* @param <T> type of the outer exception
*/
@Factory
public static <T extends Throwable> Matcher<T> hasCause(final Matcher<T> matcher) {
public static <T extends Throwable> Matcher<T> hasCause(final Matcher<? extends Throwable> matcher) {
return new ThrowableCauseMatcher<T>(matcher);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.junit.internal.matchers;

import org.junit.Test;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.internal.matchers.ThrowableCauseMatcher.hasCause;

public class ThrowableCauseMatcherTest {

@Test
public void shouldAllowCauseOfDifferentClassFromRoot() throws Exception {
NullPointerException expectedCause = new NullPointerException("expected");
Exception actual = new Exception(expectedCause);

assertThat(actual, hasCause(is(expectedCause)));
}
}
4 changes: 3 additions & 1 deletion src/test/java/org/junit/tests/AllTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.junit.experimental.categories.CategoryFilterFactoryTest;
import org.junit.internal.MethodSorterTest;
import org.junit.internal.matchers.StacktracePrintingMatcherTest;
import org.junit.internal.matchers.ThrowableCauseMatcherTest;
import org.junit.rules.DisableOnDebugTest;
import org.junit.rules.StopwatchTest;
import org.junit.runner.FilterFactoriesTest;
Expand Down Expand Up @@ -205,7 +206,8 @@
TestWithParametersTest.class,
ParameterizedNamesTest.class,
PublicClassValidatorTest.class,
DisableOnDebugTest.class
DisableOnDebugTest.class,
ThrowableCauseMatcherTest.class
})
public class AllTests {
public static Test suite() {
Expand Down

0 comments on commit 71a3221

Please sign in to comment.