1 package org.mockitoutil; 2 3 import org.junit.runner.Result; 4 import org.junit.runner.notification.Failure; 5 6 import java.util.List; 7 8 import static org.junit.Assert.assertEquals; 9 import static org.mockito.internal.util.collections.Iterables.firstOf; 10 import static org.mockitoutil.TestBase.filterLineNo; 11 12 /** 13 * Assertion utility for cleaner & easier to debug tests that inspect on JUnit's Result object 14 */ 15 public class JUnitResultAssert { 16 private Result result; 17 18 private JUnitResultAssert(Result result) { 19 this.result = result; 20 } 21 22 public void isSuccessful() { 23 if (result.wasSuccessful()) { 24 return; 25 } 26 27 throw new AssertionError(formatFailures(result.getFailures())); 28 } 29 30 /** 31 * @param expectedFailureCount - expected number of failures 32 * @param expectedException - the exception of each failure 33 */ 34 public JUnitResultAssert fails(int expectedFailureCount, Class expectedException) { 35 fails(expectedFailureCount); 36 for (Failure f : result.getFailures()) { 37 if (!expectedException.isInstance(f.getException())) { 38 throw new AssertionError("Incorrect failure type, expected: " + expectedException + ", actual: " + f.getException().getClass().getSimpleName() + "\n" + 39 formatFailures(result.getFailures())); 40 } 41 } 42 return this; 43 } 44 45 /** 46 * @param expectedFailureCount - exact number of expected failures 47 */ 48 public JUnitResultAssert fails(int expectedFailureCount) { 49 if (result.getFailures().size() != expectedFailureCount) { 50 throw new AssertionError("Wrong number of failures, expected: " + expectedFailureCount + ", actual: " + result.getFailures().size() + "\n" + 51 formatFailures(result.getFailures())); 52 } 53 return this; 54 } 55 56 /** 57 * @param expectedExceptions - failures must match the supplied sequence in order, 58 * if supplied input is empty, this method is a no-op 59 */ 60 public JUnitResultAssert failsExactly(Class ... expectedExceptions) { 61 fails(expectedExceptions.length); 62 int i = 0; 63 for (Failure f : result.getFailures()) { 64 if (!expectedExceptions[i].isInstance(f.getException())) { 65 throw new AssertionError("Actual failure #" + (i+1) 66 + " should be of type: " + expectedExceptions[i].getSimpleName() 67 + " but is of type: " + f.getException().getClass().getSimpleName() 68 + "\n" + formatFailures(result.getFailures())); 69 } 70 i++; 71 } 72 return this; 73 } 74 75 /** 76 * Expects single failure with specific exception and exception message. 77 * Automatically filters line numbers from exception messages. 78 */ 79 public JUnitResultAssert fails(Class expectedException, String exceptionMessage) { 80 fails(1, expectedException); 81 Failure f = firstOf(result.getFailures()); 82 assertEquals(filterLineNo(exceptionMessage), filterLineNo(f.getException().getMessage())); 83 return this; 84 } 85 86 /** 87 * Expects failure of given test method with given exception 88 */ 89 public JUnitResultAssert fails(String methodName, Class expectedException) { 90 for (Failure f : result.getFailures()) { 91 if (methodName.equals(f.getDescription().getMethodName()) && expectedException.isInstance(f.getException())) { 92 return this; 93 } 94 } 95 throw new AssertionError("Method '" + methodName + "' did not fail with: " + expectedException.getSimpleName() 96 + "\n" + formatFailures(result.getFailures())); 97 } 98 99 /** 100 * Expects given amount of failures, with given exception triggered by given test method 101 */ 102 public JUnitResultAssert fails(int expectedFailureCount, String methodName, Class expectedException) { 103 return fails(expectedFailureCount, expectedException) 104 .fails(methodName, expectedException); 105 } 106 107 public JUnitResultAssert succeeds(int successCount) { 108 int i = result.getRunCount() - result.getFailureCount(); 109 if (i != successCount) { 110 throw new AssertionError("Expected " + successCount + " passes but " + i + "/" + result.getRunCount() + " passed." + 111 "\n" + formatFailures(result.getFailures())); 112 } 113 return this; 114 } 115 116 private static String formatFailures(List<Failure> failures) { 117 if (failures.isEmpty()) { 118 return "<no failures>"; 119 } 120 StringBuilder sb = new StringBuilder("There were " + failures.size() + " test failures:\n"); 121 int count = 0; 122 for (Failure f : failures) { 123 sb.append(" <-----> ").append(++count).append(". ").append(f.getTrace()).append("\n"); 124 } 125 126 return sb.toString(); 127 } 128 129 /** 130 * Clean assertions for JUnit's result object 131 */ 132 public static JUnitResultAssert assertThat(Result result) { 133 return new JUnitResultAssert(result); 134 } 135 } 136