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