Home | History | Annotate | Download | only in mockitoutil
      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 
     22     private JUnitResultAssert(Result result) {
     23         this.result = result;
     24     }
     25 
     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      */
     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      */
     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      */
     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      */
     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      */
     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      */
    106     public JUnitResultAssert fails(int expectedFailureCount, String methodName, Class expectedException) {
    107         return fails(expectedFailureCount, expectedException)
    108                 .fails(methodName, expectedException);
    109     }
    110 
    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 
    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      */
    136     public static JUnitResultAssert assertThat(Result result) {
    137         return new JUnitResultAssert(result);
    138     }
    139 }
    140