From 86f323b2a73c9c250fbe25b828435aa936704ab3 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Wed, 14 Dec 2016 12:42:07 +0000 Subject: Revert matchers back to 4.10 to compile against Hamcrest 1.1 JUnit 4.12 is supposed to be built against Hamcrest 1.3 or above but external/hamcrest is still at 1.1. This reverts affected files back to their 4.10 version so that they will compile against Hamcrest 1.1 for now. Bug: 33613916 Test: make checkbuild Change-Id: Ie3c15047aa5a942ed0987c31c345725bef4db3d4 --- src/main/java/org/junit/Assume.java | 15 +- .../junit/internal/matchers/CombinableMatcher.java | 34 ++ .../java/org/junit/internal/matchers/Each.java | 24 ++ .../internal/matchers/IsCollectionContaining.java | 67 ++++ .../matchers/StacktracePrintingMatcher.java | 56 --- .../junit/internal/matchers/StringContains.java | 31 ++ .../junit/internal/matchers/SubstringMatcher.java | 28 ++ .../internal/matchers/ThrowableCauseMatcher.java | 50 --- .../internal/matchers/ThrowableMessageMatcher.java | 37 -- .../junit/internal/matchers/TypeSafeMatcher.java | 21 +- .../java/org/junit/matchers/JUnitMatchers.java | 166 ++++----- .../java/org/junit/rules/ExpectedException.java | 382 +++++++-------------- .../rules/ExpectedExceptionMatcherBuilder.java | 46 --- 13 files changed, 393 insertions(+), 564 deletions(-) create mode 100644 src/main/java/org/junit/internal/matchers/CombinableMatcher.java create mode 100644 src/main/java/org/junit/internal/matchers/Each.java create mode 100644 src/main/java/org/junit/internal/matchers/IsCollectionContaining.java delete mode 100644 src/main/java/org/junit/internal/matchers/StacktracePrintingMatcher.java create mode 100644 src/main/java/org/junit/internal/matchers/StringContains.java create mode 100644 src/main/java/org/junit/internal/matchers/SubstringMatcher.java delete mode 100644 src/main/java/org/junit/internal/matchers/ThrowableCauseMatcher.java delete mode 100644 src/main/java/org/junit/internal/matchers/ThrowableMessageMatcher.java delete mode 100644 src/main/java/org/junit/rules/ExpectedExceptionMatcherBuilder.java (limited to 'src/main') diff --git a/src/main/java/org/junit/Assume.java b/src/main/java/org/junit/Assume.java index b7687f7..c96ff99 100644 --- a/src/main/java/org/junit/Assume.java +++ b/src/main/java/org/junit/Assume.java @@ -1,12 +1,12 @@ package org.junit; import static java.util.Arrays.asList; -import static org.hamcrest.CoreMatchers.everyItem; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import org.hamcrest.Matcher; +import org.junit.internal.matchers.Each; /** * A set of methods useful for stating assumptions about the conditions in which a test is meaningful. @@ -66,12 +66,13 @@ public class Assume { assumeTrue(message, !b); } - /** - * If called with one or more null elements in objects, the test will halt and be ignored. - */ - public static void assumeNotNull(Object... objects) { - assumeThat(asList(objects), everyItem(notNullValue())); - } + /** + * If called with one or more null elements in objects, the test will halt and be ignored. + * @param objects + */ + public static void assumeNotNull(Object... objects) { + assumeThat(asList(objects), Each.each(notNullValue())); + } /** * Call to assume that actual satisfies the condition specified by matcher. diff --git a/src/main/java/org/junit/internal/matchers/CombinableMatcher.java b/src/main/java/org/junit/internal/matchers/CombinableMatcher.java new file mode 100644 index 0000000..e9e6947 --- /dev/null +++ b/src/main/java/org/junit/internal/matchers/CombinableMatcher.java @@ -0,0 +1,34 @@ +package org.junit.internal.matchers; + +import static org.hamcrest.CoreMatchers.allOf; +import static org.hamcrest.CoreMatchers.anyOf; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; + +public class CombinableMatcher extends BaseMatcher { + + private final Matcher fMatcher; + + public CombinableMatcher(Matcher matcher) { + fMatcher= matcher; + } + + public boolean matches(Object item) { + return fMatcher.matches(item); + } + + public void describeTo(Description description) { + description.appendDescriptionOf(fMatcher); + } + + @SuppressWarnings("unchecked") + public CombinableMatcher and(Matcher matcher) { + return new CombinableMatcher(allOf(matcher, fMatcher)); + } + + @SuppressWarnings("unchecked") + public CombinableMatcher or(Matcher matcher) { + return new CombinableMatcher(anyOf(matcher, fMatcher)); + } +} \ No newline at end of file diff --git a/src/main/java/org/junit/internal/matchers/Each.java b/src/main/java/org/junit/internal/matchers/Each.java new file mode 100644 index 0000000..527db3b --- /dev/null +++ b/src/main/java/org/junit/internal/matchers/Each.java @@ -0,0 +1,24 @@ +package org.junit.internal.matchers; + +import static org.hamcrest.CoreMatchers.not; +import static org.junit.internal.matchers.IsCollectionContaining.hasItem; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; + +public class Each { + public static Matcher> each(final Matcher individual) { + final Matcher> allItemsAre = not(hasItem(not(individual))); + + return new BaseMatcher>() { + public boolean matches(Object item) { + return allItemsAre.matches(item); + } + + public void describeTo(Description description) { + description.appendText("each "); + individual.describeTo(description); + } + }; + } +} diff --git a/src/main/java/org/junit/internal/matchers/IsCollectionContaining.java b/src/main/java/org/junit/internal/matchers/IsCollectionContaining.java new file mode 100644 index 0000000..4436a83 --- /dev/null +++ b/src/main/java/org/junit/internal/matchers/IsCollectionContaining.java @@ -0,0 +1,67 @@ +package org.junit.internal.matchers; + +import static org.hamcrest.core.AllOf.allOf; +import static org.hamcrest.core.IsEqual.equalTo; + +import java.util.ArrayList; +import java.util.Collection; + +import org.hamcrest.Description; +import org.hamcrest.Factory; +import org.hamcrest.Matcher; + +// Copied (hopefully temporarily) from hamcrest-library +public class IsCollectionContaining extends TypeSafeMatcher> { + private final Matcher elementMatcher; + + public IsCollectionContaining(Matcher elementMatcher) { + this.elementMatcher = elementMatcher; + } + + @Override + public boolean matchesSafely(Iterable collection) { + for (T item : collection) { + if (elementMatcher.matches(item)){ + return true; + } + } + return false; + } + + public void describeTo(Description description) { + description + .appendText("a collection containing ") + .appendDescriptionOf(elementMatcher); + } + + @Factory + public static Matcher> hasItem(Matcher elementMatcher) { + return new IsCollectionContaining(elementMatcher); + } + + @Factory + public static Matcher> hasItem(T element) { + return hasItem(equalTo(element)); + } + + @Factory + public static Matcher> hasItems(Matcher... elementMatchers) { + Collection>> all + = new ArrayList>>(elementMatchers.length); + for (Matcher elementMatcher : elementMatchers) { + all.add(hasItem(elementMatcher)); + } + return allOf(all); + } + + @Factory + public static Matcher> hasItems(T... elements) { + Collection>> all + = new ArrayList>>(elements.length); + for (T element : elements) { + all.add(hasItem(element)); + } + return allOf(all); + } + +} diff --git a/src/main/java/org/junit/internal/matchers/StacktracePrintingMatcher.java b/src/main/java/org/junit/internal/matchers/StacktracePrintingMatcher.java deleted file mode 100644 index 5d45ba3..0000000 --- a/src/main/java/org/junit/internal/matchers/StacktracePrintingMatcher.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.junit.internal.matchers; - -import java.io.PrintWriter; -import java.io.StringWriter; - -import org.hamcrest.Description; -import org.hamcrest.Factory; -import org.hamcrest.Matcher; - -/** - * A matcher that delegates to throwableMatcher and in addition appends the - * stacktrace of the actual Throwable in case of a mismatch. - */ -public class StacktracePrintingMatcher extends - org.hamcrest.TypeSafeMatcher { - - private final Matcher throwableMatcher; - - public StacktracePrintingMatcher(Matcher throwableMatcher) { - this.throwableMatcher = throwableMatcher; - } - - public void describeTo(Description description) { - throwableMatcher.describeTo(description); - } - - @Override - protected boolean matchesSafely(T item) { - return throwableMatcher.matches(item); - } - - @Override - protected void describeMismatchSafely(T item, Description description) { - throwableMatcher.describeMismatch(item, description); - description.appendText("\nStacktrace was: "); - description.appendText(readStacktrace(item)); - } - - private String readStacktrace(Throwable throwable) { - StringWriter stringWriter = new StringWriter(); - throwable.printStackTrace(new PrintWriter(stringWriter)); - return stringWriter.toString(); - } - - @Factory - public static Matcher isThrowable( - Matcher throwableMatcher) { - return new StacktracePrintingMatcher(throwableMatcher); - } - - @Factory - public static Matcher isException( - Matcher exceptionMatcher) { - return new StacktracePrintingMatcher(exceptionMatcher); - } -} diff --git a/src/main/java/org/junit/internal/matchers/StringContains.java b/src/main/java/org/junit/internal/matchers/StringContains.java new file mode 100644 index 0000000..e5f5334 --- /dev/null +++ b/src/main/java/org/junit/internal/matchers/StringContains.java @@ -0,0 +1,31 @@ +/* Copyright (c) 2000-2006 hamcrest.org + */ +package org.junit.internal.matchers; + +import org.hamcrest.Factory; +import org.hamcrest.Matcher; + +/** + * Tests if the argument is a string that contains a substring. + */ +public class StringContains extends SubstringMatcher { + public StringContains(String substring) { + super(substring); + } + + @Override + protected boolean evalSubstringOf(String s) { + return s.indexOf(substring) >= 0; + } + + @Override + protected String relationship() { + return "containing"; + } + + @Factory + public static Matcher containsString(String substring) { + return new StringContains(substring); + } + +} \ No newline at end of file diff --git a/src/main/java/org/junit/internal/matchers/SubstringMatcher.java b/src/main/java/org/junit/internal/matchers/SubstringMatcher.java new file mode 100644 index 0000000..1c65240 --- /dev/null +++ b/src/main/java/org/junit/internal/matchers/SubstringMatcher.java @@ -0,0 +1,28 @@ +package org.junit.internal.matchers; + +import org.hamcrest.Description; + +public abstract class SubstringMatcher extends TypeSafeMatcher { + + protected final String substring; + + protected SubstringMatcher(final String substring) { + this.substring = substring; + } + + @Override + public boolean matchesSafely(String item) { + return evalSubstringOf(item); + } + + public void describeTo(Description description) { + description.appendText("a string ") + .appendText(relationship()) + .appendText(" ") + .appendValue(substring); + } + + protected abstract boolean evalSubstringOf(String string); + + protected abstract String relationship(); +} \ No newline at end of file diff --git a/src/main/java/org/junit/internal/matchers/ThrowableCauseMatcher.java b/src/main/java/org/junit/internal/matchers/ThrowableCauseMatcher.java deleted file mode 100644 index 22ce8bd..0000000 --- a/src/main/java/org/junit/internal/matchers/ThrowableCauseMatcher.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.junit.internal.matchers; - -import org.hamcrest.Description; -import org.hamcrest.Factory; -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 the type of the throwable being matched - */ -public class ThrowableCauseMatcher extends - TypeSafeMatcher { - - private final Matcher causeMatcher; - - public ThrowableCauseMatcher(Matcher causeMatcher) { - this.causeMatcher = causeMatcher; - } - - public void describeTo(Description description) { - description.appendText("exception with cause "); - description.appendDescriptionOf(causeMatcher); - } - - @Override - protected boolean matchesSafely(T item) { - return causeMatcher.matches(item.getCause()); - } - - @Override - protected void describeMismatchSafely(T item, Description description) { - description.appendText("cause "); - 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 type of the outer exception - */ - @Factory - public static Matcher hasCause(final Matcher matcher) { - return new ThrowableCauseMatcher(matcher); - } -} \ No newline at end of file diff --git a/src/main/java/org/junit/internal/matchers/ThrowableMessageMatcher.java b/src/main/java/org/junit/internal/matchers/ThrowableMessageMatcher.java deleted file mode 100644 index 74386a8..0000000 --- a/src/main/java/org/junit/internal/matchers/ThrowableMessageMatcher.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.junit.internal.matchers; - -import org.hamcrest.Description; -import org.hamcrest.Factory; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; - -public class ThrowableMessageMatcher extends - TypeSafeMatcher { - - private final Matcher matcher; - - public ThrowableMessageMatcher(Matcher matcher) { - this.matcher = matcher; - } - - public void describeTo(Description description) { - description.appendText("exception with message "); - description.appendDescriptionOf(matcher); - } - - @Override - protected boolean matchesSafely(T item) { - return matcher.matches(item.getMessage()); - } - - @Override - protected void describeMismatchSafely(T item, Description description) { - description.appendText("message "); - matcher.describeMismatch(item.getMessage(), description); - } - - @Factory - public static Matcher hasMessage(final Matcher matcher) { - return new ThrowableMessageMatcher(matcher); - } -} \ No newline at end of file diff --git a/src/main/java/org/junit/internal/matchers/TypeSafeMatcher.java b/src/main/java/org/junit/internal/matchers/TypeSafeMatcher.java index 4e2cc12..794a174 100644 --- a/src/main/java/org/junit/internal/matchers/TypeSafeMatcher.java +++ b/src/main/java/org/junit/internal/matchers/TypeSafeMatcher.java @@ -3,16 +3,13 @@ package org.junit.internal.matchers; import java.lang.reflect.Method; import org.hamcrest.BaseMatcher; -import org.junit.internal.MethodSorter; /** * Convenient base class for Matchers that require a non-null value of a specific type. * This simply implements the null check, checks the type and then casts. * * @author Joe Walnes - * @deprecated Please use {@link org.hamcrest.TypeSafeMatcher}. */ -@Deprecated public abstract class TypeSafeMatcher extends BaseMatcher { private Class expectedType; @@ -26,27 +23,27 @@ public abstract class TypeSafeMatcher extends BaseMatcher { protected TypeSafeMatcher() { expectedType = findExpectedType(getClass()); } - + private static Class findExpectedType(Class fromClass) { for (Class c = fromClass; c != Object.class; c = c.getSuperclass()) { - for (Method method : MethodSorter.getDeclaredMethods(c)) { + for (Method method : c.getDeclaredMethods()) { if (isMatchesSafelyMethod(method)) { return method.getParameterTypes()[0]; } } } - + throw new Error("Cannot determine correct type for matchesSafely() method."); } - + private static boolean isMatchesSafelyMethod(Method method) { - return method.getName().equals("matchesSafely") - && method.getParameterTypes().length == 1 - && !method.isSynthetic(); + return method.getName().equals("matchesSafely") + && method.getParameterTypes().length == 1 + && !method.isSynthetic(); } - + protected TypeSafeMatcher(Class expectedType) { - this.expectedType = expectedType; + this.expectedType = expectedType; } /** diff --git a/src/main/java/org/junit/matchers/JUnitMatchers.java b/src/main/java/org/junit/matchers/JUnitMatchers.java index 13407cc..01b8489 100644 --- a/src/main/java/org/junit/matchers/JUnitMatchers.java +++ b/src/main/java/org/junit/matchers/JUnitMatchers.java @@ -1,113 +1,83 @@ package org.junit.matchers; -import org.hamcrest.CoreMatchers; import org.hamcrest.Matcher; -import org.hamcrest.core.CombinableMatcher.CombinableBothMatcher; -import org.hamcrest.core.CombinableMatcher.CombinableEitherMatcher; -import org.junit.internal.matchers.StacktracePrintingMatcher; +import org.junit.internal.matchers.CombinableMatcher; +import org.junit.internal.matchers.Each; +import org.junit.internal.matchers.IsCollectionContaining; +import org.junit.internal.matchers.StringContains; /** * Convenience import class: these are useful matchers for use with the assertThat method, but they are * not currently included in the basic CoreMatchers class from hamcrest. - * - * @since 4.4 */ public class JUnitMatchers { - /** - * @return A matcher matching any collection containing element - * @deprecated Please use {@link CoreMatchers#hasItem(Object)} instead. - */ - @Deprecated - public static Matcher> hasItem(T element) { - return CoreMatchers.hasItem(element); - } + /** + * @param element + * @return A matcher matching any collection containing element + */ + public static org.hamcrest.Matcher> hasItem(T element) { + return IsCollectionContaining.hasItem(element); + } - /** - * @return A matcher matching any collection containing an element matching elementMatcher - * @deprecated Please use {@link CoreMatchers#hasItem(Matcher)} instead. - */ - @Deprecated - public static Matcher> hasItem(Matcher elementMatcher) { - return CoreMatchers.hasItem(elementMatcher); - } + /** + * @param elementMatcher + * @return A matcher matching any collection containing an element matching elementMatcher + */ + public static org.hamcrest.Matcher> hasItem(org.hamcrest.Matcher elementMatcher) { + return IsCollectionContaining.hasItem(elementMatcher); + } - /** - * @return A matcher matching any collection containing every element in elements - * @deprecated Please use {@link CoreMatchers#hasItems(Object...)} instead. - */ - @Deprecated - public static Matcher> hasItems(T... elements) { - return CoreMatchers.hasItems(elements); - } + /** + * @param elements + * @return A matcher matching any collection containing every element in elements + */ + public static org.hamcrest.Matcher> hasItems(T... elements) { + return IsCollectionContaining.hasItems(elements); + } - /** - * @return A matcher matching any collection containing at least one element that matches - * each matcher in elementMatcher (this may be one element matching all matchers, - * or different elements matching each matcher) - * @deprecated Please use {@link CoreMatchers#hasItems(Matcher...)} instead. - */ - @Deprecated - public static Matcher> hasItems(Matcher... elementMatchers) { - return CoreMatchers.hasItems(elementMatchers); - } + /** + * @param elementMatchers + * @return A matcher matching any collection containing at least one element that matches + * each matcher in elementMatcher (this may be one element matching all matchers, + * or different elements matching each matcher) + */ + public static org.hamcrest.Matcher> hasItems(org.hamcrest.Matcher... elementMatchers) { + return IsCollectionContaining.hasItems(elementMatchers); + } - /** - * @return A matcher matching any collection in which every element matches elementMatcher - * @deprecated Please use {@link CoreMatchers#everyItem(Matcher)} instead. - */ - @Deprecated - public static Matcher> everyItem(final Matcher elementMatcher) { - return CoreMatchers.everyItem(elementMatcher); - } + /** + * @param elementMatcher + * @return A matcher matching any collection in which every element matches elementMatcher + */ + public static Matcher> everyItem(final Matcher elementMatcher) { + return Each.each(elementMatcher); + } - /** - * @return a matcher matching any string that contains substring - * @deprecated Please use {@link CoreMatchers#containsString(String)} instead. - */ - @Deprecated - public static Matcher containsString(java.lang.String substring) { - return CoreMatchers.containsString(substring); - } - - /** - * This is useful for fluently combining matchers that must both pass. For example: - *
-     *   assertThat(string, both(containsString("a")).and(containsString("b")));
-     * 
- * - * @deprecated Please use {@link CoreMatchers#both(Matcher)} instead. - */ - @Deprecated - public static CombinableBothMatcher both(Matcher matcher) { - return CoreMatchers.both(matcher); - } - - /** - * This is useful for fluently combining matchers where either may pass, for example: - *
-     *   assertThat(string, either(containsString("a")).or(containsString("b")));
-     * 
- * - * @deprecated Please use {@link CoreMatchers#either(Matcher)} instead. - */ - @Deprecated - public static CombinableEitherMatcher either(Matcher matcher) { - return CoreMatchers.either(matcher); - } - - /** - * @return A matcher that delegates to throwableMatcher and in addition - * appends the stacktrace of the actual Throwable in case of a mismatch. - */ - public static Matcher isThrowable(Matcher throwableMatcher) { - return StacktracePrintingMatcher.isThrowable(throwableMatcher); - } - - /** - * @return A matcher that delegates to exceptionMatcher and in addition - * appends the stacktrace of the actual Exception in case of a mismatch. - */ - public static Matcher isException(Matcher exceptionMatcher) { - return StacktracePrintingMatcher.isException(exceptionMatcher); - } + /** + * @param substring + * @return a matcher matching any string that contains substring + */ + public static org.hamcrest.Matcher containsString(java.lang.String substring) { + return StringContains.containsString(substring); + } + + /** + * This is useful for fluently combining matchers that must both pass. For example: + *
+	 *   assertThat(string, both(containsString("a")).and(containsString("b")));
+	 * 
+ */ + public static CombinableMatcher both(Matcher matcher) { + return new CombinableMatcher(matcher); + } + + /** + * This is useful for fluently combining matchers where either may pass, for example: + *
+	 *   assertThat(string, either(containsString("a")).or(containsString("b")));
+	 * 
+ */ + public static CombinableMatcher either(Matcher matcher) { + return new CombinableMatcher(matcher); + } } diff --git a/src/main/java/org/junit/rules/ExpectedException.java b/src/main/java/org/junit/rules/ExpectedException.java index 4d61712..bac2fba 100644 --- a/src/main/java/org/junit/rules/ExpectedException.java +++ b/src/main/java/org/junit/rules/ExpectedException.java @@ -1,270 +1,136 @@ package org.junit.rules; -import static java.lang.String.format; -import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.instanceOf; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; -import static org.junit.internal.matchers.ThrowableCauseMatcher.hasCause; -import static org.junit.internal.matchers.ThrowableMessageMatcher.hasMessage; - +import static org.junit.matchers.JUnitMatchers.both; +import static org.junit.matchers.JUnitMatchers.containsString; +import org.hamcrest.Description; import org.hamcrest.Matcher; import org.hamcrest.StringDescription; -import org.junit.AssumptionViolatedException; +import org.junit.Assert; +import org.junit.internal.matchers.TypeSafeMatcher; import org.junit.runners.model.Statement; /** - * The {@code ExpectedException} rule allows you to verify that your code - * throws a specific exception. - * - *

Usage

- * - *
 public class SimpleExpectedExceptionTest {
- *     @Rule
- *     public ExpectedException thrown= ExpectedException.none();
- *
- *     @Test
- *     public void throwsNothing() {
- *         // no exception expected, none thrown: passes.
- *     }
- *
- *     @Test
- *     public void throwsExceptionWithSpecificType() {
- *         thrown.expect(NullPointerException.class);
- *         throw new NullPointerException();
- *     }
- * }
+ * The ExpectedException Rule allows in-test specification of expected exception + * types and messages: + * + *
+ * // These tests all pass.
+ * public static class HasExpectedException {
+ * 	@Rule
+ * 	public ExpectedException thrown= ExpectedException.none();
+ * 
+ * 	@Test
+ * 	public void throwsNothing() {
+ *    // no exception expected, none thrown: passes.
+ * 	}
  * 
- * 

- * You have to add the {@code ExpectedException} rule to your test. - * This doesn't affect your existing tests (see {@code throwsNothing()}). - * After specifiying the type of the expected exception your test is - * successful when such an exception is thrown and it fails if a - * different or no exception is thrown. - * - *

- * Instead of specifying the exception's type you can characterize the - * expected exception based on other criterias, too: - * - *

    - *
  • The exception's message contains a specific text: {@link #expectMessage(String)}
  • - *
  • The exception's message complies with a Hamcrest matcher: {@link #expectMessage(Matcher)}
  • - *
  • The exception's cause complies with a Hamcrest matcher: {@link #expectCause(Matcher)}
  • - *
  • The exception itself complies with a Hamcrest matcher: {@link #expect(Matcher)}
  • - *
- * - *

- * You can combine any of the presented expect-methods. The test is - * successful if all specifications are met. - *

 @Test
- * public void throwsException() {
- *     thrown.expect(NullPointerException.class);
- *     thrown.expectMessage("happened");
- *     throw new NullPointerException("What happened?");
- * }
- * - *

AssumptionViolatedExceptions

- *

- * JUnit uses {@link AssumptionViolatedException}s for indicating that a test - * provides no useful information. (See {@link org.junit.Assume} for more - * information.) You have to call {@code assume} methods before you set - * expectations of the {@code ExpectedException} rule. In this case the rule - * will not handle consume the exceptions and it can be handled by the - * framework. E.g. the following test is ignored by JUnit's default runner. - * - *

 @Test
- * public void ignoredBecauseOfFailedAssumption() {
- *     assumeTrue(false); // throws AssumptionViolatedException
- *     thrown.expect(NullPointerException.class);
- * }
- * - *

AssertionErrors

- * - *

- * JUnit uses {@link AssertionError}s for indicating that a test is failing. You - * have to call {@code assert} methods before you set expectations of the - * {@code ExpectedException} rule, if they should be handled by the framework. - * E.g. the following test fails because of the {@code assertTrue} statement. - * - *

 @Test
- * public void throwsUnhandled() {
- *     assertTrue(false); // throws AssertionError
- *     thrown.expect(NullPointerException.class);
- * }
- * - *

Missing Exceptions

- *

- * By default missing exceptions are reported with an error message - * like "Expected test to throw an instance of foo". You can configure a different - * message by means of {@link #reportMissingExceptionWithMessage(String)}. You - * can use a {@code %s} placeholder for the description of the expected - * exception. E.g. "Test doesn't throw %s." will fail with the error message - * "Test doesn't throw an instance of foo.". - * - * @since 4.7 + * @Test + * public void throwsNullPointerException() { + * thrown.expect(NullPointerException.class); + * throw new NullPointerException(); + * } + * + * @Test + * public void throwsNullPointerExceptionWithMessage() { + * thrown.expect(NullPointerException.class); + * thrown.expectMessage("happened?"); + * thrown.expectMessage(startsWith("What")); + * throw new NullPointerException("What happened?"); + * } + * } + *

*/ public class ExpectedException implements TestRule { - /** - * Returns a {@linkplain TestRule rule} that expects no exception to - * be thrown (identical to behavior without this rule). - */ - public static ExpectedException none() { - return new ExpectedException(); - } - - private final ExpectedExceptionMatcherBuilder matcherBuilder = new ExpectedExceptionMatcherBuilder(); - - private String missingExceptionMessage= "Expected test to throw %s"; - - private ExpectedException() { - } - - /** - * This method does nothing. Don't use it. - * @deprecated AssertionErrors are handled by default since JUnit 4.12. Just - * like in JUnit <= 4.10. - */ - @Deprecated - public ExpectedException handleAssertionErrors() { - return this; - } - - /** - * This method does nothing. Don't use it. - * @deprecated AssumptionViolatedExceptions are handled by default since - * JUnit 4.12. Just like in JUnit <= 4.10. - */ - @Deprecated - public ExpectedException handleAssumptionViolatedExceptions() { - return this; - } - - /** - * Specifies the failure message for tests that are expected to throw - * an exception but do not throw any. You can use a {@code %s} placeholder for - * the description of the expected exception. E.g. "Test doesn't throw %s." - * will fail with the error message - * "Test doesn't throw an instance of foo.". - * - * @param message exception detail message - * @return the rule itself - */ - public ExpectedException reportMissingExceptionWithMessage(String message) { - missingExceptionMessage = message; - return this; - } - - public Statement apply(Statement base, - org.junit.runner.Description description) { - return new ExpectedExceptionStatement(base); - } - - /** - * Verify that your code throws an exception that is matched by - * a Hamcrest matcher. - *
 @Test
-     * public void throwsExceptionThatCompliesWithMatcher() {
-     *     NullPointerException e = new NullPointerException();
-     *     thrown.expect(is(e));
-     *     throw e;
-     * }
- */ - public void expect(Matcher matcher) { - matcherBuilder.add(matcher); - } - - /** - * Verify that your code throws an exception that is an - * instance of specific {@code type}. - *
 @Test
-     * public void throwsExceptionWithSpecificType() {
-     *     thrown.expect(NullPointerException.class);
-     *     throw new NullPointerException();
-     * }
- */ - public void expect(Class type) { - expect(instanceOf(type)); - } - - /** - * Verify that your code throws an exception whose message contains - * a specific text. - *
 @Test
-     * public void throwsExceptionWhoseMessageContainsSpecificText() {
-     *     thrown.expectMessage("happened");
-     *     throw new NullPointerException("What happened?");
-     * }
- */ - public void expectMessage(String substring) { - expectMessage(containsString(substring)); - } - - /** - * Verify that your code throws an exception whose message is matched - * by a Hamcrest matcher. - *
 @Test
-     * public void throwsExceptionWhoseMessageCompliesWithMatcher() {
-     *     thrown.expectMessage(startsWith("What"));
-     *     throw new NullPointerException("What happened?");
-     * }
- */ - public void expectMessage(Matcher matcher) { - expect(hasMessage(matcher)); - } - - /** - * Verify that your code throws an exception whose cause is matched by - * a Hamcrest matcher. - *
 @Test
-     * public void throwsExceptionWhoseCauseCompliesWithMatcher() {
-     *     NullPointerException expectedCause = new NullPointerException();
-     *     thrown.expectCause(is(expectedCause));
-     *     throw new IllegalArgumentException("What happened?", cause);
-     * }
- */ - public void expectCause(Matcher expectedCause) { - expect(hasCause(expectedCause)); - } - - private class ExpectedExceptionStatement extends Statement { - private final Statement next; - - public ExpectedExceptionStatement(Statement base) { - next = base; - } - - @Override - public void evaluate() throws Throwable { - try { - next.evaluate(); - } catch (Throwable e) { - handleException(e); - return; - } - if (isAnyExceptionExpected()) { - failDueToMissingException(); - } - } - } - - private void handleException(Throwable e) throws Throwable { - if (isAnyExceptionExpected()) { - assertThat(e, matcherBuilder.build()); - } else { - throw e; - } - } - - private boolean isAnyExceptionExpected() { - return matcherBuilder.expectsThrowable(); - } - - private void failDueToMissingException() throws AssertionError { - fail(missingExceptionMessage()); - } - - private String missingExceptionMessage() { - String expectation= StringDescription.toString(matcherBuilder.build()); - return format(missingExceptionMessage, expectation); - } + /** + * @return a Rule that expects no exception to be thrown + * (identical to behavior without this Rule) + */ + public static ExpectedException none() { + return new ExpectedException(); + } + + private Matcher fMatcher= null; + + private ExpectedException() { + + } + + public Statement apply(Statement base, + org.junit.runner.Description description) { + return new ExpectedExceptionStatement(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) matcher; + else + fMatcher= both(fMatcher).and(matcher); + } + + /** + * Adds to the list of requirements for any thrown exception that it + * should be an instance of {@code type} + */ + public void expect(Class type) { + expect(instanceOf(type)); + } + + /** + * Adds to the list of requirements for any thrown exception that it + * should contain string {@code substring} + */ + public void expectMessage(String substring) { + expectMessage(containsString(substring)); + } + + /** + * Adds {@code matcher} to the list of requirements for the message + * returned from any thrown exception. + */ + public void expectMessage(Matcher matcher) { + expect(hasMessage(matcher)); + } + + private class ExpectedExceptionStatement extends Statement { + private final Statement fNext; + + public ExpectedExceptionStatement(Statement base) { + fNext= base; + } + + @Override + public void evaluate() throws Throwable { + try { + fNext.evaluate(); + } catch (Throwable e) { + if (fMatcher == null) + throw e; + Assert.assertThat(e, fMatcher); + return; + } + if (fMatcher != null) + throw new AssertionError("Expected test to throw " + + StringDescription.toString(fMatcher)); + } + } + + private Matcher hasMessage(final Matcher matcher) { + return new TypeSafeMatcher() { + public void describeTo(Description description) { + description.appendText("exception with message "); + description.appendDescriptionOf(matcher); + } + + @Override + public boolean matchesSafely(Throwable item) { + return matcher.matches(item.getMessage()); + } + }; + } } diff --git a/src/main/java/org/junit/rules/ExpectedExceptionMatcherBuilder.java b/src/main/java/org/junit/rules/ExpectedExceptionMatcherBuilder.java deleted file mode 100644 index e7d94c4..0000000 --- a/src/main/java/org/junit/rules/ExpectedExceptionMatcherBuilder.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.junit.rules; - -import static org.hamcrest.CoreMatchers.allOf; -import static org.junit.matchers.JUnitMatchers.isThrowable; - -import java.util.ArrayList; -import java.util.List; - -import org.hamcrest.Matcher; - -/** - * Builds special matcher used by {@link ExpectedException}. - */ -class ExpectedExceptionMatcherBuilder { - - private final List> matchers = new ArrayList>(); - - void add(Matcher matcher) { - matchers.add(matcher); - } - - boolean expectsThrowable() { - return !matchers.isEmpty(); - } - - Matcher build() { - return isThrowable(allOfTheMatchers()); - } - - private Matcher allOfTheMatchers() { - if (matchers.size() == 1) { - return cast(matchers.get(0)); - } - return allOf(castedMatchers()); - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private List> castedMatchers() { - return new ArrayList>((List) matchers); - } - - @SuppressWarnings("unchecked") - private Matcher cast(Matcher singleMatcher) { - return (Matcher) singleMatcher; - } -} -- cgit v1.2.3