@@ -298,7 +298,7 @@ public static void assertArrayEquals(String message, Object[] expecteds,
298298 public static void assertArrayEquals (Object [] expecteds , Object [] actuals ) {
299299 assertArrayEquals (null , expecteds , actuals );
300300 }
301-
301+
302302 /**
303303 * Asserts that two boolean arrays are equal. If they are not, an
304304 * {@link AssertionError} is thrown with the given message. If
@@ -313,8 +313,8 @@ public static void assertArrayEquals(Object[] expecteds, Object[] actuals) {
313313 public static void assertArrayEquals (String message , boolean [] expecteds ,
314314 boolean [] actuals ) throws ArrayComparisonFailure {
315315 internalArrayEquals (message , expecteds , actuals );
316- }
317-
316+ }
317+
318318 /**
319319 * Asserts that two boolean arrays are equal. If they are not, an
320320 * {@link AssertionError} is thrown. If <code>expected</code> and
@@ -955,4 +955,64 @@ public static <T> void assertThat(String reason, T actual,
955955 Matcher <? super T > matcher ) {
956956 MatcherAssert .assertThat (reason , actual , matcher );
957957 }
958+
959+ /**
960+ * This interface facilitates the use of expectThrows from Java 8. It allows method references
961+ * to void methods (that declare checked exceptions) to be passed directly into expectThrows
962+ * without wrapping. It is not meant to be implemented directly.
963+ *
964+ * @since 4.13
965+ */
966+ public interface ThrowingRunnable {
967+ void run () throws Throwable ;
968+ }
969+
970+ /**
971+ * Asserts that {@code runnable} throws an exception of type {@code expectedThrowable} when
972+ * executed. If it does not throw an exception, an {@link AssertionError} is thrown. If it
973+ * throws the wrong type of exception, an {@code AssertionError} is thrown describing the
974+ * mismatch; the exception that was actually thrown can be obtained by calling {@link
975+ * AssertionError#getCause}.
976+ *
977+ * @param expectedThrowable the expected type of the exception
978+ * @param runnable a function that is expected to throw an exception when executed
979+ * @since 4.13
980+ */
981+ public static void assertThrows (Class <? extends Throwable > expectedThrowable , ThrowingRunnable runnable ) {
982+ expectThrows (expectedThrowable , runnable );
983+ }
984+
985+ /**
986+ * Asserts that {@code runnable} throws an exception of type {@code expectedThrowable} when
987+ * executed. If it does, the exception object is returned. If it does not throw an exception, an
988+ * {@link AssertionError} is thrown. If it throws the wrong type of exception, an {@code
989+ * AssertionError} is thrown describing the mismatch; the exception that was actually thrown can
990+ * be obtained by calling {@link AssertionError#getCause}.
991+ *
992+ * @param expectedThrowable the expected type of the exception
993+ * @param runnable a function that is expected to throw an exception when executed
994+ * @return the exception thrown by {@code runnable}
995+ * @since 4.13
996+ */
997+ public static <T extends Throwable > T expectThrows (Class <T > expectedThrowable , ThrowingRunnable runnable ) {
998+ try {
999+ runnable .run ();
1000+ } catch (Throwable actualThrown ) {
1001+ if (expectedThrowable .isInstance (actualThrown )) {
1002+ @ SuppressWarnings ("unchecked" ) T retVal = (T ) actualThrown ;
1003+ return retVal ;
1004+ } else {
1005+ String mismatchMessage = format ("unexpected exception type thrown;" ,
1006+ expectedThrowable .getSimpleName (), actualThrown .getClass ().getSimpleName ());
1007+
1008+ // The AssertionError(String, Throwable) ctor is only available on JDK7.
1009+ AssertionError assertionError = new AssertionError (mismatchMessage );
1010+ assertionError .initCause (actualThrown );
1011+ throw assertionError ;
1012+ }
1013+ }
1014+ String message = String .format ("expected %s to be thrown, but nothing was thrown" ,
1015+ expectedThrowable .getSimpleName ());
1016+ throw new AssertionError (message );
1017+ }
9581018}
0 commit comments