Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Custom matcher for ExpectedException (refactoring)

ExpectedExceptionMatcher now collects all the matchers and internally
provides custom matchers for checking the message and the cause of an
exception.
  • Loading branch information...
commit 23793cd92c4c0f8449e2edaec745437c5ebbd619 1 parent a68b42c
@marcphilipp marcphilipp authored
View
52 src/main/java/org/junit/rules/ExpectedException.java
@@ -1,13 +1,10 @@
package org.junit.rules;
-import static org.hamcrest.CoreMatchers.both;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertThat;
-import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.StringDescription;
-import org.hamcrest.TypeSafeMatcher;
import org.junit.internal.AssumptionViolatedException;
import org.junit.runners.model.Statement;
@@ -89,7 +86,7 @@ public static ExpectedException none() {
return new ExpectedException();
}
- private Matcher<Object> fMatcher= null;
+ private final ExpectedExceptionMatcher fMatcher= new ExpectedExceptionMatcher();
private boolean handleAssumptionViolatedExceptions= false;
@@ -117,14 +114,8 @@ public Statement apply(Statement base,
* Adds {@code matcher} to the list of requirements for any thrown
* exception.
*/
- // Should be able to remove this suppression in some brave new hamcrest
- // world.
- @SuppressWarnings("unchecked")
public void expect(Matcher<?> matcher) {
- if (fMatcher == null)
- fMatcher= (Matcher<Object>) matcher;
- else
- fMatcher= both(fMatcher).and((Matcher<Object>) matcher);
+ fMatcher.and(matcher);
}
/**
@@ -148,7 +139,7 @@ public void expectMessage(String substring) {
* from any thrown exception.
*/
public void expectMessage(Matcher<String> matcher) {
- expect(hasMessage(matcher));
+ fMatcher.andHasMessage(matcher);
}
/**
@@ -156,7 +147,7 @@ public void expectMessage(Matcher<String> matcher) {
* any thrown exception.
*/
public void expectCause(Matcher<? extends Throwable> expectedCause) {
- expect(hasCause(expectedCause));
+ fMatcher.andHasCause(expectedCause);
}
private class ExpectedExceptionStatement extends Statement {
@@ -180,7 +171,7 @@ public void evaluate() throws Throwable {
handleException(e);
return;
}
- if (fMatcher != null)
+ if (fMatcher.expectsThrowable())
throw new AssertionError("Expected test to throw "
+ StringDescription.toString(fMatcher));
}
@@ -195,36 +186,9 @@ private void optionallyHandleException(Throwable e, boolean handleException)
}
private void handleException(Throwable e) throws Throwable {
- if (fMatcher == null)
+ if (fMatcher.expectsThrowable())
+ assertThat(e, fMatcher);
+ else
throw e;
- assertThat(e, fMatcher);
- }
-
- private Matcher<Throwable> hasMessage(final Matcher<String> matcher) {
- return new TypeSafeMatcher<Throwable>() {
- public void describeTo(Description description) {
- description.appendText("exception with message ");
- description.appendDescriptionOf(matcher);
- }
-
- @Override
- public boolean matchesSafely(Throwable item) {
- return matcher.matches(item.getMessage());
- }
- };
- }
-
- private Matcher<Throwable> hasCause(final Matcher<? extends Throwable> causeMatcher) {
- return new TypeSafeMatcher<Throwable>() {
- public void describeTo(Description description) {
- description.appendText("exception with cause ");
- description.appendDescriptionOf(causeMatcher);
- }
-
- @Override
- public boolean matchesSafely(Throwable item) {
- return causeMatcher.matches(item.getCause());
- }
- };
}
}
View
92 src/main/java/org/junit/rules/ExpectedExceptionMatcher.java
@@ -0,0 +1,92 @@
+package org.junit.rules;
+
+import static org.hamcrest.CoreMatchers.allOf;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.hamcrest.TypeSafeMatcher;
+
+/**
+ * Special matcher used by {@link ExpectedException}.
+ */
+class ExpectedExceptionMatcher extends TypeSafeMatcher<Throwable> {
+
+ private final List<Matcher<?>> fMatchers = new ArrayList<Matcher<?>>();
+ private Matcher<?> fCompositeMatcher;
+
+ void and(Matcher<?> matcher) {
+ fMatchers.add(matcher);
+ fCompositeMatcher= createCompositeMatcher();
+ }
+
+ void andHasMessage(Matcher<String> matcher) {
+ and(hasMessage(matcher));
+ }
+
+ void andHasCause(Matcher<? extends Throwable> causeMatcher) {
+ and(hasCause(causeMatcher));
+ }
+
+ boolean expectsThrowable() {
+ return !fMatchers.isEmpty();
+ }
+
+ @Override
+ protected boolean matchesSafely(Throwable item) {
+ return fCompositeMatcher.matches(item);
+ }
+
+ public void describeTo(Description description) {
+ fCompositeMatcher.describeTo(description);
+ }
+
+ private Matcher<?> createCompositeMatcher() {
+ if (fMatchers.size() == 1) {
+ return fMatchers.get(0);
+ }
+ return allOf(castedMatchers());
+ }
+
+ // Should be able to remove this suppression in some brave new hamcrest
+ // world.
+ @SuppressWarnings("unchecked")
+ private List<Matcher<? super Object>> castedMatchers() {
+ List<Matcher<? super Object>> castedMatchers = new LinkedList<Matcher<? super Object>>();
+ for (Matcher<?> matcher : fMatchers) {
+ castedMatchers.add((Matcher<? super Object>) matcher);
+ }
+ return castedMatchers;
+ }
+
+ private Matcher<Throwable> hasMessage(final Matcher<String> matcher) {
+ return new TypeSafeMatcher<Throwable>() {
+ public void describeTo(Description description) {
+ description.appendText("exception with message ");
+ description.appendDescriptionOf(matcher);
+ }
+
+ @Override
+ public boolean matchesSafely(Throwable item) {
+ return matcher.matches(item.getMessage());
+ }
+ };
+ }
+
+ private Matcher<Throwable> hasCause(final Matcher<? extends Throwable> causeMatcher) {
+ return new TypeSafeMatcher<Throwable>() {
+ public void describeTo(Description description) {
+ description.appendText("exception with cause ");
+ description.appendDescriptionOf(causeMatcher);
+ }
+
+ @Override
+ public boolean matchesSafely(Throwable item) {
+ return causeMatcher.matches(item.getCause());
+ }
+ };
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.