aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Duffin <paulduffin@google.com>2017-01-10 10:47:30 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-01-10 10:47:30 +0000
commitcd58d3905ff5efdebf5df158e2b59a82ae67b618 (patch)
tree5e35bd76d6575654fdba8c7d6d64c11e55327755
parent72f680fa68f0e717b0fc3fc55bab3eaff6179556 (diff)
parent0453c6d6818090fb674a9d8e16033e9c9db503b5 (diff)
downloadjunit-cd58d3905ff5efdebf5df158e2b59a82ae67b618.tar.gz
Revert matchers back to 4.10 to compile against Hamcrest 1.1 am: 86f323b2a7 am: e20af47911
am: 0453c6d681 Change-Id: I513c274dc6ce48cd6b02679d37461efac7131688
-rw-r--r--README.version1
-rw-r--r--src/main/java/org/junit/Assume.java15
-rw-r--r--src/main/java/org/junit/internal/matchers/CombinableMatcher.java34
-rw-r--r--src/main/java/org/junit/internal/matchers/Each.java24
-rw-r--r--src/main/java/org/junit/internal/matchers/IsCollectionContaining.java67
-rw-r--r--src/main/java/org/junit/internal/matchers/StacktracePrintingMatcher.java56
-rw-r--r--src/main/java/org/junit/internal/matchers/StringContains.java31
-rw-r--r--src/main/java/org/junit/internal/matchers/SubstringMatcher.java28
-rw-r--r--src/main/java/org/junit/internal/matchers/ThrowableCauseMatcher.java50
-rw-r--r--src/main/java/org/junit/internal/matchers/ThrowableMessageMatcher.java37
-rw-r--r--src/main/java/org/junit/internal/matchers/TypeSafeMatcher.java21
-rw-r--r--src/main/java/org/junit/matchers/JUnitMatchers.java166
-rw-r--r--src/main/java/org/junit/rules/ExpectedException.java382
-rw-r--r--src/main/java/org/junit/rules/ExpectedExceptionMatcherBuilder.java46
14 files changed, 394 insertions, 564 deletions
diff --git a/README.version b/README.version
index dfa89da..0ca87b6 100644
--- a/README.version
+++ b/README.version
@@ -5,3 +5,4 @@ BugComponent: 40416
Local Changes:
Remove DisableOnDebug (new in 4.12) as it is not supported on Android
Remove support for stuck threads
+ Revert matchers back to 4.10 to compile against Hamcrest 1.1
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 <code>objects</code>, 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 <code>objects</code>, 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 <code>actual</code> satisfies the condition specified by <code>matcher</code>.
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<T> extends BaseMatcher<T> {
+
+ private final Matcher<? extends T> fMatcher;
+
+ public CombinableMatcher(Matcher<? extends T> matcher) {
+ fMatcher= matcher;
+ }
+
+ public boolean matches(Object item) {
+ return fMatcher.matches(item);
+ }
+
+ public void describeTo(Description description) {
+ description.appendDescriptionOf(fMatcher);
+ }
+
+ @SuppressWarnings("unchecked")
+ public CombinableMatcher<T> and(Matcher<? extends T> matcher) {
+ return new CombinableMatcher<T>(allOf(matcher, fMatcher));
+ }
+
+ @SuppressWarnings("unchecked")
+ public CombinableMatcher<T> or(Matcher<? extends T> matcher) {
+ return new CombinableMatcher<T>(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 <T> Matcher<Iterable<T>> each(final Matcher<T> individual) {
+ final Matcher<Iterable<T>> allItemsAre = not(hasItem(not(individual)));
+
+ return new BaseMatcher<Iterable<T>>() {
+ 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<T> extends TypeSafeMatcher<Iterable<T>> {
+ private final Matcher<? extends T> elementMatcher;
+
+ public IsCollectionContaining(Matcher<? extends T> elementMatcher) {
+ this.elementMatcher = elementMatcher;
+ }
+
+ @Override
+ public boolean matchesSafely(Iterable<T> 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 <T> Matcher<Iterable<T>> hasItem(Matcher<? extends T> elementMatcher) {
+ return new IsCollectionContaining<T>(elementMatcher);
+ }
+
+ @Factory
+ public static <T> Matcher<Iterable<T>> hasItem(T element) {
+ return hasItem(equalTo(element));
+ }
+
+ @Factory
+ public static <T> Matcher<Iterable<T>> hasItems(Matcher<? extends T>... elementMatchers) {
+ Collection<Matcher<? extends Iterable<T>>> all
+ = new ArrayList<Matcher<? extends Iterable<T>>>(elementMatchers.length);
+ for (Matcher<? extends T> elementMatcher : elementMatchers) {
+ all.add(hasItem(elementMatcher));
+ }
+ return allOf(all);
+ }
+
+ @Factory
+ public static <T> Matcher<Iterable<T>> hasItems(T... elements) {
+ Collection<Matcher<? extends Iterable<T>>> all
+ = new ArrayList<Matcher<? extends Iterable<T>>>(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<T extends Throwable> extends
- org.hamcrest.TypeSafeMatcher<T> {
-
- private final Matcher<T> throwableMatcher;
-
- public StacktracePrintingMatcher(Matcher<T> 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 <T extends Throwable> Matcher<T> isThrowable(
- Matcher<T> throwableMatcher) {
- return new StacktracePrintingMatcher<T>(throwableMatcher);
- }
-
- @Factory
- public static <T extends Exception> Matcher<T> isException(
- Matcher<T> exceptionMatcher) {
- return new StacktracePrintingMatcher<T>(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<String> 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<String> {
+
+ 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 <T> the type of the throwable being matched
- */
-public class ThrowableCauseMatcher<T extends Throwable> extends
- TypeSafeMatcher<T> {
-
- private final Matcher<? extends Throwable> causeMatcher;
-
- public ThrowableCauseMatcher(Matcher<? extends Throwable> 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 <T> type of the outer exception
- */
- @Factory
- public static <T extends Throwable> Matcher<T> hasCause(final Matcher<? extends Throwable> matcher) {
- return new ThrowableCauseMatcher<T>(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<T extends Throwable> extends
- TypeSafeMatcher<T> {
-
- private final Matcher<String> matcher;
-
- public ThrowableMessageMatcher(Matcher<String> 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 <T extends Throwable> Matcher<T> hasMessage(final Matcher<String> matcher) {
- return new ThrowableMessageMatcher<T>(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<T> extends BaseMatcher<T> {
private Class<?> expectedType;
@@ -26,27 +23,27 @@ public abstract class TypeSafeMatcher<T> extends BaseMatcher<T> {
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<T> 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 <T> Matcher<Iterable<? super T>> hasItem(T element) {
- return CoreMatchers.hasItem(element);
- }
+ /**
+ * @param element
+ * @return A matcher matching any collection containing element
+ */
+ public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> 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 <T> Matcher<Iterable<? super T>> hasItem(Matcher<? super T> elementMatcher) {
- return CoreMatchers.<T>hasItem(elementMatcher);
- }
+ /**
+ * @param elementMatcher
+ * @return A matcher matching any collection containing an element matching elementMatcher
+ */
+ public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItem(org.hamcrest.Matcher<? extends T> 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 <T> Matcher<Iterable<T>> hasItems(T... elements) {
- return CoreMatchers.hasItems(elements);
- }
+ /**
+ * @param elements
+ * @return A matcher matching any collection containing every element in elements
+ */
+ public static <T> org.hamcrest.Matcher<java.lang.Iterable<T>> 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 <T> Matcher<Iterable<T>> hasItems(Matcher<? super T>... 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 <T> org.hamcrest.Matcher<java.lang.Iterable<T>> hasItems(org.hamcrest.Matcher<? extends T>... 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 <T> Matcher<Iterable<T>> everyItem(final Matcher<T> elementMatcher) {
- return CoreMatchers.everyItem(elementMatcher);
- }
+ /**
+ * @param elementMatcher
+ * @return A matcher matching any collection in which every element matches elementMatcher
+ */
+ public static <T> Matcher<Iterable<T>> everyItem(final Matcher<T> 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<java.lang.String> containsString(java.lang.String substring) {
- return CoreMatchers.containsString(substring);
- }
-
- /**
- * This is useful for fluently combining matchers that must both pass. For example:
- * <pre>
- * assertThat(string, both(containsString("a")).and(containsString("b")));
- * </pre>
- *
- * @deprecated Please use {@link CoreMatchers#both(Matcher)} instead.
- */
- @Deprecated
- public static <T> CombinableBothMatcher<T> both(Matcher<? super T> matcher) {
- return CoreMatchers.both(matcher);
- }
-
- /**
- * This is useful for fluently combining matchers where either may pass, for example:
- * <pre>
- * assertThat(string, either(containsString("a")).or(containsString("b")));
- * </pre>
- *
- * @deprecated Please use {@link CoreMatchers#either(Matcher)} instead.
- */
- @Deprecated
- public static <T> CombinableEitherMatcher<T> either(Matcher<? super T> 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 <T extends Throwable> Matcher<T> isThrowable(Matcher<T> 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 <T extends Exception> Matcher<T> isException(Matcher<T> exceptionMatcher) {
- return StacktracePrintingMatcher.isException(exceptionMatcher);
- }
+ /**
+ * @param substring
+ * @return a matcher matching any string that contains substring
+ */
+ public static org.hamcrest.Matcher<java.lang.String> containsString(java.lang.String substring) {
+ return StringContains.containsString(substring);
+ }
+
+ /**
+ * This is useful for fluently combining matchers that must both pass. For example:
+ * <pre>
+ * assertThat(string, both(containsString("a")).and(containsString("b")));
+ * </pre>
+ */
+ public static <T> CombinableMatcher<T> both(Matcher<T> matcher) {
+ return new CombinableMatcher<T>(matcher);
+ }
+
+ /**
+ * This is useful for fluently combining matchers where either may pass, for example:
+ * <pre>
+ * assertThat(string, either(containsString("a")).or(containsString("b")));
+ * </pre>
+ */
+ public static <T> CombinableMatcher<T> either(Matcher<T> matcher) {
+ return new CombinableMatcher<T>(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.
- *
- * <h3>Usage</h3>
- *
- * <pre> public class SimpleExpectedExceptionTest {
- * &#064;Rule
- * public ExpectedException thrown= ExpectedException.none();
- *
- * &#064;Test
- * public void throwsNothing() {
- * // no exception expected, none thrown: passes.
- * }
- *
- * &#064;Test
- * public void throwsExceptionWithSpecificType() {
- * thrown.expect(NullPointerException.class);
- * throw new NullPointerException();
- * }
- * }</pre>
+ * The ExpectedException Rule allows in-test specification of expected exception
+ * types and messages:
+ *
+ * <pre>
+ * // These tests all pass.
+ * public static class HasExpectedException {
+ * &#064;Rule
+ * public ExpectedException thrown= ExpectedException.none();
+ *
+ * &#064;Test
+ * public void throwsNothing() {
+ * // no exception expected, none thrown: passes.
+ * }
*
- * <p>
- * 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.
- *
- * <p>
- * Instead of specifying the exception's type you can characterize the
- * expected exception based on other criterias, too:
- *
- * <ul>
- * <li>The exception's message contains a specific text: {@link #expectMessage(String)}</li>
- * <li>The exception's message complies with a Hamcrest matcher: {@link #expectMessage(Matcher)}</li>
- * <li>The exception's cause complies with a Hamcrest matcher: {@link #expectCause(Matcher)}</li>
- * <li>The exception itself complies with a Hamcrest matcher: {@link #expect(Matcher)}</li>
- * </ul>
- *
- * <p>
- * You can combine any of the presented expect-methods. The test is
- * successful if all specifications are met.
- * <pre> &#064;Test
- * public void throwsException() {
- * thrown.expect(NullPointerException.class);
- * thrown.expectMessage(&quot;happened&quot;);
- * throw new NullPointerException(&quot;What happened?&quot;);
- * }</pre>
- *
- * <h3>AssumptionViolatedExceptions</h3>
- * <p>
- * 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.
- *
- * <pre> &#064;Test
- * public void ignoredBecauseOfFailedAssumption() {
- * assumeTrue(false); // throws AssumptionViolatedException
- * thrown.expect(NullPointerException.class);
- * }</pre>
- *
- * <h3>AssertionErrors</h3>
- *
- * <p>
- * 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.
- *
- * <pre> &#064;Test
- * public void throwsUnhandled() {
- * assertTrue(false); // throws AssertionError
- * thrown.expect(NullPointerException.class);
- * }</pre>
- *
- * <h3>Missing Exceptions</h3>
- * <p>
- * 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
+ * &#064;Test
+ * public void throwsNullPointerException() {
+ * thrown.expect(NullPointerException.class);
+ * throw new NullPointerException();
+ * }
+ *
+ * &#064;Test
+ * public void throwsNullPointerExceptionWithMessage() {
+ * thrown.expect(NullPointerException.class);
+ * thrown.expectMessage(&quot;happened?&quot;);
+ * thrown.expectMessage(startsWith(&quot;What&quot;));
+ * throw new NullPointerException(&quot;What happened?&quot;);
+ * }
+ * }
+ * </pre>
*/
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 &lt;= 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 &lt;= 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.
- * <pre> &#064;Test
- * public void throwsExceptionThatCompliesWithMatcher() {
- * NullPointerException e = new NullPointerException();
- * thrown.expect(is(e));
- * throw e;
- * }</pre>
- */
- public void expect(Matcher<?> matcher) {
- matcherBuilder.add(matcher);
- }
-
- /**
- * Verify that your code throws an exception that is an
- * instance of specific {@code type}.
- * <pre> &#064;Test
- * public void throwsExceptionWithSpecificType() {
- * thrown.expect(NullPointerException.class);
- * throw new NullPointerException();
- * }</pre>
- */
- public void expect(Class<? extends Throwable> type) {
- expect(instanceOf(type));
- }
-
- /**
- * Verify that your code throws an exception whose message contains
- * a specific text.
- * <pre> &#064;Test
- * public void throwsExceptionWhoseMessageContainsSpecificText() {
- * thrown.expectMessage(&quot;happened&quot;);
- * throw new NullPointerException(&quot;What happened?&quot;);
- * }</pre>
- */
- public void expectMessage(String substring) {
- expectMessage(containsString(substring));
- }
-
- /**
- * Verify that your code throws an exception whose message is matched
- * by a Hamcrest matcher.
- * <pre> &#064;Test
- * public void throwsExceptionWhoseMessageCompliesWithMatcher() {
- * thrown.expectMessage(startsWith(&quot;What&quot;));
- * throw new NullPointerException(&quot;What happened?&quot;);
- * }</pre>
- */
- public void expectMessage(Matcher<String> matcher) {
- expect(hasMessage(matcher));
- }
-
- /**
- * Verify that your code throws an exception whose cause is matched by
- * a Hamcrest matcher.
- * <pre> &#064;Test
- * public void throwsExceptionWhoseCauseCompliesWithMatcher() {
- * NullPointerException expectedCause = new NullPointerException();
- * thrown.expectCause(is(expectedCause));
- * throw new IllegalArgumentException(&quot;What happened?&quot;, cause);
- * }</pre>
- */
- public void expectCause(Matcher<? extends Throwable> 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<Object> 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<Object>) 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<? extends Throwable> type) {
+ expect(instanceOf(type));
+ }
+
+ /**
+ * Adds to the list of requirements for any thrown exception that it
+ * should <em>contain</em> 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<String> 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<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());
+ }
+ };
+ }
}
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<Matcher<?>> matchers = new ArrayList<Matcher<?>>();
-
- void add(Matcher<?> matcher) {
- matchers.add(matcher);
- }
-
- boolean expectsThrowable() {
- return !matchers.isEmpty();
- }
-
- Matcher<Throwable> build() {
- return isThrowable(allOfTheMatchers());
- }
-
- private Matcher<Throwable> allOfTheMatchers() {
- if (matchers.size() == 1) {
- return cast(matchers.get(0));
- }
- return allOf(castedMatchers());
- }
-
- @SuppressWarnings({"unchecked", "rawtypes"})
- private List<Matcher<? super Throwable>> castedMatchers() {
- return new ArrayList<Matcher<? super Throwable>>((List) matchers);
- }
-
- @SuppressWarnings("unchecked")
- private Matcher<Throwable> cast(Matcher<?> singleMatcher) {
- return (Matcher<Throwable>) singleMatcher;
- }
-}