package org.mockitoutil; import org.junit.runner.Result; import org.junit.runner.notification.Failure; import java.util.List; import static org.junit.Assert.assertEquals; import static org.mockito.internal.util.collections.Iterables.firstOf; import static org.mockitoutil.TestBase.filterLineNo; /** * Assertion utility for cleaner & easier to debug tests that inspect on JUnit's Result object */ public class JUnitResultAssert { private Result result; private JUnitResultAssert(Result result) { this.result = result; } public void isSuccessful() { if (result.wasSuccessful()) { return; } throw new AssertionError(formatFailures(result.getFailures())); } /** * @param expectedFailureCount - expected number of failures * @param expectedException - the exception of each failure */ public JUnitResultAssert fails(int expectedFailureCount, Class expectedException) { fails(expectedFailureCount); for (Failure f : result.getFailures()) { if (!expectedException.isInstance(f.getException())) { throw new AssertionError("Incorrect failure type, expected: " + expectedException + ", actual: " + f.getException().getClass().getSimpleName() + "\n" + formatFailures(result.getFailures())); } } return this; } /** * @param expectedFailureCount - exact number of expected failures */ public JUnitResultAssert fails(int expectedFailureCount) { if (result.getFailures().size() != expectedFailureCount) { throw new AssertionError("Wrong number of failures, expected: " + expectedFailureCount + ", actual: " + result.getFailures().size() + "\n" + formatFailures(result.getFailures())); } return this; } /** * @param expectedExceptions - failures must match the supplied sequence in order, * if supplied input is empty, this method is a no-op */ public JUnitResultAssert failsExactly(Class ... expectedExceptions) { fails(expectedExceptions.length); int i = 0; for (Failure f : result.getFailures()) { if (!expectedExceptions[i].isInstance(f.getException())) { throw new AssertionError("Actual failure #" + (i+1) + " should be of type: " + expectedExceptions[i].getSimpleName() + " but is of type: " + f.getException().getClass().getSimpleName() + "\n" + formatFailures(result.getFailures())); } i++; } return this; } /** * Expects single failure with specific exception and exception message. * Automatically filters line numbers from exception messages. */ public JUnitResultAssert fails(Class expectedException, String exceptionMessage) { fails(1, expectedException); Failure f = firstOf(result.getFailures()); assertEquals(filterLineNo(exceptionMessage), filterLineNo(f.getException().getMessage())); return this; } /** * Expects failure of given test method with given exception */ public JUnitResultAssert fails(String methodName, Class expectedException) { for (Failure f : result.getFailures()) { if (methodName.equals(f.getDescription().getMethodName()) && expectedException.isInstance(f.getException())) { return this; } } throw new AssertionError("Method '" + methodName + "' did not fail with: " + expectedException.getSimpleName() + "\n" + formatFailures(result.getFailures())); } /** * Expects given amount of failures, with given exception triggered by given test method */ public JUnitResultAssert fails(int expectedFailureCount, String methodName, Class expectedException) { return fails(expectedFailureCount, expectedException) .fails(methodName, expectedException); } public JUnitResultAssert succeeds(int successCount) { int i = result.getRunCount() - result.getFailureCount(); if (i != successCount) { throw new AssertionError("Expected " + successCount + " passes but " + i + "/" + result.getRunCount() + " passed." + "\n" + formatFailures(result.getFailures())); } return this; } private static String formatFailures(List<Failure> failures) { if (failures.isEmpty()) { return "<no failures>"; } StringBuilder sb = new StringBuilder("There were " + failures.size() + " test failures:\n"); int count = 0; for (Failure f : failures) { sb.append(" <-----> ").append(++count).append(". ").append(f.getTrace()).append("\n"); } return sb.toString(); } /** * Clean assertions for JUnit's result object */ public static JUnitResultAssert assertThat(Result result) { return new JUnitResultAssert(result); } }