Home | History | Annotate | Download | only in exceptions
      1 /*
      2  * Copyright (c) 2007 Mockito contributors
      3  * This program is made available under the terms of the MIT License.
      4  */
      5 
      6 package org.mockito.internal.exceptions;
      7 
      8 import org.mockito.exceptions.base.MockitoAssertionError;
      9 import org.mockito.exceptions.base.MockitoException;
     10 import org.mockito.exceptions.misusing.*;
     11 import org.mockito.exceptions.verification.MoreThanAllowedActualInvocations;
     12 import org.mockito.exceptions.verification.NeverWantedButInvoked;
     13 import org.mockito.exceptions.verification.NoInteractionsWanted;
     14 import org.mockito.exceptions.verification.SmartNullPointerException;
     15 import org.mockito.exceptions.verification.TooLittleActualInvocations;
     16 import org.mockito.exceptions.verification.TooManyActualInvocations;
     17 import org.mockito.exceptions.verification.VerificationInOrderFailure;
     18 import org.mockito.exceptions.verification.WantedButNotInvoked;
     19 import org.mockito.internal.debugging.LocationImpl;
     20 import org.mockito.internal.exceptions.util.ScenarioPrinter;
     21 import org.mockito.internal.junit.ExceptionFactory;
     22 import org.mockito.internal.matchers.LocalizedMatcher;
     23 import org.mockito.internal.util.MockUtil;
     24 import org.mockito.invocation.DescribedInvocation;
     25 import org.mockito.invocation.Invocation;
     26 import org.mockito.invocation.InvocationOnMock;
     27 import org.mockito.invocation.Location;
     28 import org.mockito.listeners.InvocationListener;
     29 import org.mockito.mock.MockName;
     30 import org.mockito.mock.SerializableMode;
     31 
     32 import java.lang.reflect.Field;
     33 import java.lang.reflect.Method;
     34 import java.util.ArrayList;
     35 import java.util.Collection;
     36 import java.util.List;
     37 
     38 import static org.mockito.internal.reporting.Pluralizer.pluralize;
     39 import static org.mockito.internal.reporting.Pluralizer.were_exactly_x_interactions;
     40 import static org.mockito.internal.util.StringUtil.join;
     41 
     42 /**
     43  * Reports verification and misusing errors.
     44  * <p>
     45  * One of the key points of mocking library is proper verification/exception
     46  * messages. All messages in one place makes it easier to tune and amend them.
     47  * <p>
     48  * Reporter can be injected and therefore is easily testable.
     49  * <p>
     50  * Generally, exception messages are full of line breaks to make them easy to
     51  * read (xunit plugins take only fraction of screen on modern IDEs).
     52  */
     53 public class Reporter {
     54 
     55     private final static String NON_PUBLIC_PARENT = "Mocking methods declared on non-public parent classes is not supported.";
     56 
     57     private Reporter() {
     58     }
     59 
     60     public static MockitoException checkedExceptionInvalid(Throwable t) {
     61         return new MockitoException(join(
     62                 "Checked exception is invalid for this method!",
     63                 "Invalid: " + t
     64         ));
     65     }
     66 
     67     public static MockitoException cannotStubWithNullThrowable() {
     68         return new MockitoException(join(
     69                 "Cannot stub with null throwable!"
     70         ));
     71 
     72     }
     73 
     74     public static MockitoException unfinishedStubbing(Location location) {
     75         return new UnfinishedStubbingException(join(
     76                 "Unfinished stubbing detected here:",
     77                 location,
     78                 "",
     79                 "E.g. thenReturn() may be missing.",
     80                 "Examples of correct stubbing:",
     81                 "    when(mock.isOk()).thenReturn(true);",
     82                 "    when(mock.isOk()).thenThrow(exception);",
     83                 "    doThrow(exception).when(mock).someVoidMethod();",
     84                 "Hints:",
     85                 " 1. missing thenReturn()",
     86                 " 2. you are trying to stub a final method, which is not supported",
     87                 " 3: you are stubbing the behaviour of another mock inside before 'thenReturn' instruction if completed",
     88                 ""
     89         ));
     90     }
     91 
     92     public static MockitoException incorrectUseOfApi() {
     93         return new MockitoException(join(
     94                 "Incorrect use of API detected here:",
     95                 new LocationImpl(),
     96                 "",
     97                 "You probably stored a reference to OngoingStubbing returned by when() and called stubbing methods like thenReturn() on this reference more than once.",
     98                 "Examples of correct usage:",
     99                 "    when(mock.isOk()).thenReturn(true).thenReturn(false).thenThrow(exception);",
    100                 "    when(mock.isOk()).thenReturn(true, false).thenThrow(exception);",
    101                 ""
    102         ));
    103     }
    104 
    105     public static MockitoException missingMethodInvocation() {
    106         return new MissingMethodInvocationException(join(
    107                 "when() requires an argument which has to be 'a method call on a mock'.",
    108                 "For example:",
    109                 "    when(mock.getArticles()).thenReturn(articles);",
    110                 "",
    111                 "Also, this error might show up because:",
    112                 "1. you stub either of: final/private/equals()/hashCode() methods.",
    113                 "   Those methods *cannot* be stubbed/verified.",
    114                 "   " + NON_PUBLIC_PARENT,
    115                 "2. inside when() you don't call method on mock but on some other object.",
    116                 ""
    117         ));
    118     }
    119 
    120     public static MockitoException unfinishedVerificationException(Location location) {
    121         return new UnfinishedVerificationException(join(
    122                 "Missing method call for verify(mock) here:",
    123                 location,
    124                 "",
    125                 "Example of correct verification:",
    126                 "    verify(mock).doSomething()",
    127                 "",
    128                 "Also, this error might show up because you verify either of: final/private/equals()/hashCode() methods.",
    129                 "Those methods *cannot* be stubbed/verified.",
    130                 NON_PUBLIC_PARENT,
    131                 ""
    132         ));
    133     }
    134 
    135     public static MockitoException notAMockPassedToVerify(Class<?> type) {
    136         return new NotAMockException(join(
    137                 "Argument passed to verify() is of type " + type.getSimpleName() + " and is not a mock!",
    138                 "Make sure you place the parenthesis correctly!",
    139                 "See the examples of correct verifications:",
    140                 "    verify(mock).someMethod();",
    141                 "    verify(mock, times(10)).someMethod();",
    142                 "    verify(mock, atLeastOnce()).someMethod();"
    143         ));
    144     }
    145 
    146     public static MockitoException nullPassedToVerify() {
    147         return new NullInsteadOfMockException(join(
    148                 "Argument passed to verify() should be a mock but is null!",
    149                 "Examples of correct verifications:",
    150                 "    verify(mock).someMethod();",
    151                 "    verify(mock, times(10)).someMethod();",
    152                 "    verify(mock, atLeastOnce()).someMethod();",
    153                 "    not: verify(mock.someMethod());",
    154                 "Also, if you use @Mock annotation don't miss initMocks()"
    155         ));
    156     }
    157 
    158     public static MockitoException notAMockPassedToWhenMethod() {
    159         return new NotAMockException(join(
    160                 "Argument passed to when() is not a mock!",
    161                 "Example of correct stubbing:",
    162                 "    doThrow(new RuntimeException()).when(mock).someMethod();"
    163         ));
    164     }
    165 
    166     public static MockitoException nullPassedToWhenMethod() {
    167         return new NullInsteadOfMockException(join(
    168                 "Argument passed to when() is null!",
    169                 "Example of correct stubbing:",
    170                 "    doThrow(new RuntimeException()).when(mock).someMethod();",
    171                 "Also, if you use @Mock annotation don't miss initMocks()"
    172         ));
    173     }
    174 
    175     public static MockitoException mocksHaveToBePassedToVerifyNoMoreInteractions() {
    176         return new MockitoException(join(
    177                 "Method requires argument(s)!",
    178                 "Pass mocks that should be verified, e.g:",
    179                 "    verifyNoMoreInteractions(mockOne, mockTwo);",
    180                 "    verifyZeroInteractions(mockOne, mockTwo);",
    181                 ""
    182         ));
    183     }
    184 
    185     public static MockitoException notAMockPassedToVerifyNoMoreInteractions() {
    186         return new NotAMockException(join(
    187                 "Argument(s) passed is not a mock!",
    188                 "Examples of correct verifications:",
    189                 "    verifyNoMoreInteractions(mockOne, mockTwo);",
    190                 "    verifyZeroInteractions(mockOne, mockTwo);",
    191                 ""
    192         ));
    193     }
    194 
    195     public static MockitoException nullPassedToVerifyNoMoreInteractions() {
    196         return new NullInsteadOfMockException(join(
    197                 "Argument(s) passed is null!",
    198                 "Examples of correct verifications:",
    199                 "    verifyNoMoreInteractions(mockOne, mockTwo);",
    200                 "    verifyZeroInteractions(mockOne, mockTwo);"
    201         ));
    202     }
    203 
    204     public static MockitoException notAMockPassedWhenCreatingInOrder() {
    205         return new NotAMockException(join(
    206                 "Argument(s) passed is not a mock!",
    207                 "Pass mocks that require verification in order.",
    208                 "For example:",
    209                 "    InOrder inOrder = inOrder(mockOne, mockTwo);"
    210         ));
    211     }
    212 
    213     public static MockitoException nullPassedWhenCreatingInOrder() {
    214         return new NullInsteadOfMockException(join(
    215                 "Argument(s) passed is null!",
    216                 "Pass mocks that require verification in order.",
    217                 "For example:",
    218                 "    InOrder inOrder = inOrder(mockOne, mockTwo);"
    219         ));
    220     }
    221 
    222     public static MockitoException mocksHaveToBePassedWhenCreatingInOrder() {
    223         return new MockitoException(join(
    224                 "Method requires argument(s)!",
    225                 "Pass mocks that require verification in order.",
    226                 "For example:",
    227                 "    InOrder inOrder = inOrder(mockOne, mockTwo);"
    228         ));
    229     }
    230 
    231     public static MockitoException inOrderRequiresFamiliarMock() {
    232         return new MockitoException(join(
    233                 "InOrder can only verify mocks that were passed in during creation of InOrder.",
    234                 "For example:",
    235                 "    InOrder inOrder = inOrder(mockOne);",
    236                 "    inOrder.verify(mockOne).doStuff();"
    237         ));
    238     }
    239 
    240     public static MockitoException invalidUseOfMatchers(int expectedMatchersCount, List<LocalizedMatcher> recordedMatchers) {
    241         return new InvalidUseOfMatchersException(join(
    242                 "Invalid use of argument matchers!",
    243                 expectedMatchersCount + " matchers expected, " + recordedMatchers.size() + " recorded:" +
    244                         locationsOf(recordedMatchers),
    245                 "",
    246                 "This exception may occur if matchers are combined with raw values:",
    247                 "    //incorrect:",
    248                 "    someMethod(anyObject(), \"raw String\");",
    249                 "When using matchers, all arguments have to be provided by matchers.",
    250                 "For example:",
    251                 "    //correct:",
    252                 "    someMethod(anyObject(), eq(\"String by matcher\"));",
    253                 "",
    254                 "For more info see javadoc for Matchers class.",
    255                 ""
    256         ));
    257     }
    258 
    259     public static MockitoException incorrectUseOfAdditionalMatchers(String additionalMatcherName, int expectedSubMatchersCount, Collection<LocalizedMatcher> matcherStack) {
    260         return new InvalidUseOfMatchersException(join(
    261                 "Invalid use of argument matchers inside additional matcher " + additionalMatcherName + " !",
    262                 new LocationImpl(),
    263                 "",
    264                 expectedSubMatchersCount + " sub matchers expected, " + matcherStack.size() + " recorded:",
    265                 locationsOf(matcherStack),
    266                 "",
    267                 "This exception may occur if matchers are combined with raw values:",
    268                 "    //incorrect:",
    269                 "    someMethod(AdditionalMatchers.and(isNotNull(), \"raw String\");",
    270                 "When using matchers, all arguments have to be provided by matchers.",
    271                 "For example:",
    272                 "    //correct:",
    273                 "    someMethod(AdditionalMatchers.and(isNotNull(), eq(\"raw String\"));",
    274                 "",
    275                 "For more info see javadoc for Matchers and AdditionalMatchers classes.",
    276                 ""
    277         ));
    278     }
    279 
    280     public static MockitoException stubPassedToVerify() {
    281         return new CannotVerifyStubOnlyMock(join(
    282                 "Argument passed to verify() is a stubOnly() mock, not a full blown mock!",
    283                 "If you intend to verify invocations on a mock, don't use stubOnly() in its MockSettings."
    284         ));
    285     }
    286 
    287     public static MockitoException reportNoSubMatchersFound(String additionalMatcherName) {
    288         return new InvalidUseOfMatchersException(join(
    289                 "No matchers found for additional matcher " + additionalMatcherName,
    290                 new LocationImpl(),
    291                 ""
    292         ));
    293     }
    294 
    295 
    296     private static Object locationsOf(Collection<LocalizedMatcher> matchers) {
    297         List<String> description = new ArrayList<String>();
    298         for (LocalizedMatcher matcher : matchers)
    299             description.add(matcher.getLocation().toString());
    300         return join(description.toArray());
    301     }
    302 
    303     public static AssertionError argumentsAreDifferent(String wanted, String actual, Location actualLocation) {
    304         String message = join("Argument(s) are different! Wanted:",
    305                               wanted,
    306                               new LocationImpl(),
    307                               "Actual invocation has different arguments:",
    308                               actual,
    309                               actualLocation,
    310                               ""
    311         );
    312 
    313         return ExceptionFactory.createArgumentsAreDifferentException(message, wanted, actual);
    314     }
    315 
    316     public static MockitoAssertionError wantedButNotInvoked(DescribedInvocation wanted) {
    317         return new WantedButNotInvoked(createWantedButNotInvokedMessage(wanted));
    318     }
    319 
    320     public static MockitoAssertionError wantedButNotInvoked(DescribedInvocation wanted, List<? extends DescribedInvocation> invocations) {
    321         String allInvocations;
    322         if (invocations.isEmpty()) {
    323             allInvocations = "Actually, there were zero interactions with this mock.\n";
    324         } else {
    325             StringBuilder sb = new StringBuilder(
    326                     "\nHowever, there " + were_exactly_x_interactions(invocations.size()) + " with this mock:\n");
    327             for (DescribedInvocation i : invocations) {
    328                 sb.append(i.toString())
    329                   .append("\n")
    330                   .append(i.getLocation())
    331                   .append("\n\n");
    332             }
    333             allInvocations = sb.toString();
    334         }
    335 
    336         String message = createWantedButNotInvokedMessage(wanted);
    337         return new WantedButNotInvoked(message + allInvocations);
    338     }
    339 
    340     private static String createWantedButNotInvokedMessage(DescribedInvocation wanted) {
    341         return join(
    342                 "Wanted but not invoked:",
    343                 wanted.toString(),
    344                 new LocationImpl(),
    345                 ""
    346         );
    347     }
    348 
    349     public static MockitoAssertionError wantedButNotInvokedInOrder(DescribedInvocation wanted, DescribedInvocation previous) {
    350         return new VerificationInOrderFailure(join(
    351                 "Verification in order failure",
    352                 "Wanted but not invoked:",
    353                 wanted.toString(),
    354                 new LocationImpl(),
    355                 "Wanted anywhere AFTER following interaction:",
    356                 previous.toString(),
    357                 previous.getLocation(),
    358                 ""
    359         ));
    360     }
    361 
    362     public static MockitoAssertionError tooManyActualInvocations(int wantedCount, int actualCount, DescribedInvocation wanted, List<Location> locations) {
    363         String message = createTooManyInvocationsMessage(wantedCount, actualCount, wanted, locations);
    364         return new TooManyActualInvocations(message);
    365     }
    366 
    367     private static String createTooManyInvocationsMessage(int wantedCount, int actualCount, DescribedInvocation wanted,
    368                                                           List<Location> invocations) {
    369         return join(
    370                 wanted.toString(),
    371                 "Wanted " + pluralize(wantedCount) + ":",
    372                 new LocationImpl(),
    373                 "But was " + pluralize(actualCount) + ":",
    374                 createAllLocationsMessage(invocations),
    375                 ""
    376         );
    377     }
    378 
    379     public static MockitoAssertionError neverWantedButInvoked(DescribedInvocation wanted, List<Location> invocations) {
    380         return new NeverWantedButInvoked(join(
    381                 wanted.toString(),
    382                 "Never wanted here:",
    383                 new LocationImpl(),
    384                 "But invoked here:",
    385                 createAllLocationsMessage(invocations)
    386         ));
    387     }
    388 
    389     public static MockitoAssertionError tooManyActualInvocationsInOrder(int wantedCount, int actualCount, DescribedInvocation wanted, List<Location> invocations) {
    390         String message = createTooManyInvocationsMessage(wantedCount, actualCount, wanted, invocations);
    391         return new VerificationInOrderFailure(join(
    392                 "Verification in order failure:" + message
    393         ));
    394     }
    395 
    396     private static String createAllLocationsMessage(List<Location> locations) {
    397         if (locations == null) {
    398             return "\n";
    399         }
    400         StringBuilder sb = new StringBuilder();
    401         for (Location location : locations) {
    402             sb.append(location).append("\n");
    403         }
    404         return sb.toString();
    405     }
    406 
    407     private static String createTooLittleInvocationsMessage(org.mockito.internal.reporting.Discrepancy discrepancy,
    408                                                             DescribedInvocation wanted,
    409                                                             List<Location> locations) {
    410         return join(
    411                 wanted.toString(),
    412                 "Wanted " + discrepancy.getPluralizedWantedCount() + (discrepancy.getWantedCount() == 0 ? "." : ":"),
    413                 new LocationImpl(),
    414                 "But was " + discrepancy.getPluralizedActualCount() + (discrepancy.getActualCount() == 0 ? "." : ":"),
    415                 createAllLocationsMessage(locations)
    416         );
    417     }
    418 
    419     public static MockitoAssertionError tooLittleActualInvocations(org.mockito.internal.reporting.Discrepancy discrepancy, DescribedInvocation wanted, List<Location> allLocations) {
    420         String message = createTooLittleInvocationsMessage(discrepancy, wanted, allLocations);
    421 
    422         return new TooLittleActualInvocations(message);
    423     }
    424 
    425     public static MockitoAssertionError tooLittleActualInvocationsInOrder(org.mockito.internal.reporting.Discrepancy discrepancy, DescribedInvocation wanted, List<Location> locations) {
    426         String message = createTooLittleInvocationsMessage(discrepancy, wanted, locations);
    427 
    428         return new VerificationInOrderFailure(join(
    429                 "Verification in order failure:" + message
    430         ));
    431     }
    432 
    433     public static MockitoAssertionError noMoreInteractionsWanted(Invocation undesired, List<VerificationAwareInvocation> invocations) {
    434         ScenarioPrinter scenarioPrinter = new ScenarioPrinter();
    435         String scenario = scenarioPrinter.print(invocations);
    436 
    437         return new NoInteractionsWanted(join(
    438                 "No interactions wanted here:",
    439                 new LocationImpl(),
    440                 "But found this interaction on mock '" + safelyGetMockName(undesired.getMock()) + "':",
    441                 undesired.getLocation(),
    442                 scenario
    443         ));
    444     }
    445 
    446     public static MockitoAssertionError noMoreInteractionsWantedInOrder(Invocation undesired) {
    447         return new VerificationInOrderFailure(join(
    448                 "No interactions wanted here:",
    449                 new LocationImpl(),
    450                 "But found this interaction on mock '" + safelyGetMockName(undesired.getMock()) + "':",
    451                 undesired.getLocation()
    452         ));
    453     }
    454 
    455     public static MockitoException cannotMockClass(Class<?> clazz, String reason) {
    456         return new MockitoException(join(
    457                 "Cannot mock/spy " + clazz.toString(),
    458                 "Mockito cannot mock/spy because :",
    459                 " - " + reason
    460         ));
    461     }
    462 
    463     public static MockitoException cannotStubVoidMethodWithAReturnValue(String methodName) {
    464         return new CannotStubVoidMethodWithReturnValue(join(
    465                 "'" + methodName + "' is a *void method* and it *cannot* be stubbed with a *return value*!",
    466                 "Voids are usually stubbed with Throwables:",
    467                 "    doThrow(exception).when(mock).someVoidMethod();",
    468                 "If you need to set the void method to do nothing you can use:",
    469                 "    doNothing().when(mock).someVoidMethod();",
    470                 "For more information, check out the javadocs for Mockito.doNothing().",
    471                 "***",
    472                 "If you're unsure why you're getting above error read on.",
    473                 "Due to the nature of the syntax above problem might occur because:",
    474                 "1. The method you are trying to stub is *overloaded*. Make sure you are calling the right overloaded version.",
    475                 "2. Somewhere in your test you are stubbing *final methods*. Sorry, Mockito does not verify/stub final methods.",
    476                 "3. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - ",
    477                 "   - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.",
    478                 "4. " + NON_PUBLIC_PARENT,
    479                 ""
    480         ));
    481     }
    482 
    483     public static MockitoException onlyVoidMethodsCanBeSetToDoNothing() {
    484         return new MockitoException(join(
    485                 "Only void methods can doNothing()!",
    486                 "Example of correct use of doNothing():",
    487                 "    doNothing().",
    488                 "    doThrow(new RuntimeException())",
    489                 "    .when(mock).someVoidMethod();",
    490                 "Above means:",
    491                 "someVoidMethod() does nothing the 1st time but throws an exception the 2nd time is called"
    492         ));
    493     }
    494 
    495     public static MockitoException wrongTypeOfReturnValue(String expectedType, String actualType, String methodName) {
    496         return new WrongTypeOfReturnValue(join(
    497                 actualType + " cannot be returned by " + methodName + "()",
    498                 methodName + "() should return " + expectedType,
    499                 "***",
    500                 "If you're unsure why you're getting above error read on.",
    501                 "Due to the nature of the syntax above problem might occur because:",
    502                 "1. This exception *might* occur in wrongly written multi-threaded tests.",
    503                 "   Please refer to Mockito FAQ on limitations of concurrency testing.",
    504                 "2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - ",
    505                 "   - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.",
    506                 ""
    507         ));
    508     }
    509 
    510     public static MockitoException wrongTypeReturnedByDefaultAnswer(Object mock, String expectedType, String actualType, String methodName) {
    511         return new WrongTypeOfReturnValue(join(
    512                 "Default answer returned a result with the wrong type:",
    513                 actualType + " cannot be returned by " + methodName + "()",
    514                 methodName + "() should return " + expectedType,
    515                 "",
    516                 "The default answer of " + safelyGetMockName(mock) + " that was configured on the mock is probably incorrectly implemented.",
    517                 ""
    518         ));
    519     }
    520 
    521     public static MoreThanAllowedActualInvocations wantedAtMostX(int maxNumberOfInvocations, int foundSize) {
    522         return new MoreThanAllowedActualInvocations(join("Wanted at most " + pluralize(maxNumberOfInvocations) + " but was " + foundSize));
    523     }
    524 
    525     public static MockitoException misplacedArgumentMatcher(List<LocalizedMatcher> lastMatchers) {
    526         return new InvalidUseOfMatchersException(join(
    527                 "Misplaced or misused argument matcher detected here:",
    528                 locationsOf(lastMatchers),
    529                 "",
    530                 "You cannot use argument matchers outside of verification or stubbing.",
    531                 "Examples of correct usage of argument matchers:",
    532                 "    when(mock.get(anyInt())).thenReturn(null);",
    533                 "    doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());",
    534                 "    verify(mock).someMethod(contains(\"foo\"))",
    535                 "",
    536                 "This message may appear after an NullPointerException if the last matcher is returning an object ",
    537                 "like any() but the stubbed method signature expect a primitive argument, in this case,",
    538                 "use primitive alternatives.",
    539                 "    when(mock.get(any())); // bad use, will raise NPE",
    540                 "    when(mock.get(anyInt())); // correct usage use",
    541                 "",
    542                 "Also, this error might show up because you use argument matchers with methods that cannot be mocked.",
    543                 "Following methods *cannot* be stubbed/verified: final/private/equals()/hashCode().",
    544                 NON_PUBLIC_PARENT,
    545                 ""
    546         ));
    547     }
    548 
    549     public static MockitoException smartNullPointerException(String invocation, Location location) {
    550         return new SmartNullPointerException(join(
    551                 "You have a NullPointerException here:",
    552                 new LocationImpl(),
    553                 "because this method call was *not* stubbed correctly:",
    554                 location,
    555                 invocation,
    556                 ""
    557         ));
    558     }
    559 
    560     public static MockitoException noArgumentValueWasCaptured() {
    561         return new MockitoException(join(
    562                 "No argument value was captured!",
    563                 "You might have forgotten to use argument.capture() in verify()...",
    564                 "...or you used capture() in stubbing but stubbed method was not called.",
    565                 "Be aware that it is recommended to use capture() only with verify()",
    566                 "",
    567                 "Examples of correct argument capturing:",
    568                 "    ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);",
    569                 "    verify(mock).doSomething(argument.capture());",
    570                 "    assertEquals(\"John\", argument.getValue().getName());",
    571                 ""
    572         ));
    573     }
    574 
    575     public static MockitoException extraInterfacesDoesNotAcceptNullParameters() {
    576         return new MockitoException(join(
    577                 "extraInterfaces() does not accept null parameters."
    578         ));
    579     }
    580 
    581     public static MockitoException extraInterfacesAcceptsOnlyInterfaces(Class<?> wrongType) {
    582         return new MockitoException(join(
    583                 "extraInterfaces() accepts only interfaces.",
    584                 "You passed following type: " + wrongType.getSimpleName() + " which is not an interface."
    585         ));
    586     }
    587 
    588     public static MockitoException extraInterfacesCannotContainMockedType(Class<?> wrongType) {
    589         return new MockitoException(join(
    590                 "extraInterfaces() does not accept the same type as the mocked type.",
    591                 "You mocked following type: " + wrongType.getSimpleName(),
    592                 "and you passed the same very interface to the extraInterfaces()"
    593         ));
    594     }
    595 
    596     public static MockitoException extraInterfacesRequiresAtLeastOneInterface() {
    597         return new MockitoException(join(
    598                 "extraInterfaces() requires at least one interface."
    599         ));
    600     }
    601 
    602     public static MockitoException mockedTypeIsInconsistentWithSpiedInstanceType(Class<?> mockedType, Object spiedInstance) {
    603         return new MockitoException(join(
    604                 "Mocked type must be the same as the type of your spied instance.",
    605                 "Mocked type must be: " + spiedInstance.getClass().getSimpleName() + ", but is: " + mockedType.getSimpleName(),
    606                 "  //correct spying:",
    607                 "  spy = mock( ->ArrayList.class<- , withSettings().spiedInstance( ->new ArrayList()<- );",
    608                 "  //incorrect - types don't match:",
    609                 "  spy = mock( ->List.class<- , withSettings().spiedInstance( ->new ArrayList()<- );"
    610         ));
    611     }
    612 
    613     public static MockitoException cannotCallAbstractRealMethod() {
    614         return new MockitoException(join(
    615                 "Cannot call abstract real method on java object!",
    616                 "Calling real methods is only possible when mocking non abstract method.",
    617                 "  //correct example:",
    618                 "  when(mockOfConcreteClass.nonAbstractMethod()).thenCallRealMethod();"
    619         ));
    620     }
    621 
    622     public static MockitoException cannotVerifyToString() {
    623         return new MockitoException(join(
    624                 "Mockito cannot verify toString()",
    625                 "toString() is too often used behind of scenes  (i.e. during String concatenation, in IDE debugging views). " +
    626                         "Verifying it may give inconsistent or hard to understand results. " +
    627                         "Not to mention that verifying toString() most likely hints awkward design (hard to explain in a short exception message. Trust me...)",
    628                 "However, it is possible to stub toString(). Stubbing toString() smells a bit funny but there are rare, legitimate use cases."
    629         ));
    630     }
    631 
    632     public static MockitoException moreThanOneAnnotationNotAllowed(String fieldName) {
    633         return new MockitoException("You cannot have more than one Mockito annotation on a field!\n" +
    634                                             "The field '" + fieldName + "' has multiple Mockito annotations.\n" +
    635                                             "For info how to use annotations see examples in javadoc for MockitoAnnotations class.");
    636     }
    637 
    638     public static MockitoException unsupportedCombinationOfAnnotations(String undesiredAnnotationOne, String undesiredAnnotationTwo) {
    639         return new MockitoException("This combination of annotations is not permitted on a single field:\n" +
    640                                             "@" + undesiredAnnotationOne + " and @" + undesiredAnnotationTwo);
    641     }
    642 
    643     public static MockitoException cannotInitializeForSpyAnnotation(String fieldName, Exception details) {
    644         return new MockitoException(join("Cannot instantiate a @Spy for '" + fieldName + "' field.",
    645                                          "You haven't provided the instance for spying at field declaration so I tried to construct the instance.",
    646                                          "However, I failed because: " + details.getMessage(),
    647                                          "Examples of correct usage of @Spy:",
    648                                          "   @Spy List mock = new LinkedList();",
    649                                          "   @Spy Foo foo; //only if Foo has parameterless constructor",
    650                                          "   //also, don't forget about MockitoAnnotations.initMocks();",
    651                                          ""), details);
    652     }
    653 
    654     public static MockitoException cannotInitializeForInjectMocksAnnotation(String fieldName, String causeMessage) {
    655         return new MockitoException(join("Cannot instantiate @InjectMocks field named '" + fieldName + "'! Cause: "+causeMessage,
    656                                          "You haven't provided the instance at field declaration so I tried to construct the instance.",
    657                                          "Examples of correct usage of @InjectMocks:",
    658                                          "   @InjectMocks Service service = new Service();",
    659                                          "   @InjectMocks Service service;",
    660                                          "   //and... don't forget about some @Mocks for injection :)",
    661                                          ""));
    662     }
    663 
    664     public static MockitoException atMostAndNeverShouldNotBeUsedWithTimeout() {
    665         return new FriendlyReminderException(join("",
    666                                                   "Don't panic! I'm just a friendly reminder!",
    667                                                   "timeout() should not be used with atMost() or never() because...",
    668                                                   "...it does not make much sense - the test would have passed immediately in concurrency",
    669                                                   "We kept this method only to avoid compilation errors when upgrading Mockito.",
    670                                                   "In future release we will remove timeout(x).atMost(y) from the API.",
    671                                                   "If you want to find out more please refer to issue 235",
    672                                                   ""));
    673     }
    674 
    675     public static MockitoException fieldInitialisationThrewException(Field field, Throwable details) {
    676         return new MockitoException(join(
    677                 "Cannot instantiate @InjectMocks field named '" + field.getName() + "' of type '" + field.getType() + "'.",
    678                 "You haven't provided the instance at field declaration so I tried to construct the instance.",
    679                 "However the constructor or the initialization block threw an exception : " + details.getMessage(),
    680                 ""), details);
    681 
    682     }
    683 
    684     public static MockitoException methodDoesNotAcceptParameter(String method, String parameter) {
    685         return new MockitoException(method + "() does not accept " + parameter + " See the Javadoc.");
    686     }
    687 
    688     public static MockitoException invocationListenersRequiresAtLeastOneListener() {
    689         return new MockitoException("invocationListeners() requires at least one listener");
    690     }
    691 
    692     public static MockitoException invocationListenerThrewException(InvocationListener listener, Throwable listenerThrowable) {
    693         return new MockitoException(join(
    694                 "The invocation listener with type " + listener.getClass().getName(),
    695                 "threw an exception : " + listenerThrowable.getClass().getName() + listenerThrowable.getMessage()), listenerThrowable);
    696     }
    697 
    698     public static MockitoException cannotInjectDependency(Field field, Object matchingMock, Exception details) {
    699         return new MockitoException(join(
    700                 "Mockito couldn't inject mock dependency '" + safelyGetMockName(matchingMock) + "' on field ",
    701                 "'" + field + "'",
    702                 "whose type '" + field.getDeclaringClass().getCanonicalName() + "' was annotated by @InjectMocks in your test.",
    703                 "Also I failed because: " + exceptionCauseMessageIfAvailable(details),
    704                 ""
    705         ), details);
    706     }
    707 
    708     private static String exceptionCauseMessageIfAvailable(Exception details) {
    709         if (details.getCause() == null) {
    710             return details.getMessage();
    711         }
    712         return details.getCause().getMessage();
    713     }
    714 
    715     public static MockitoException mockedTypeIsInconsistentWithDelegatedInstanceType(Class<?> mockedType, Object delegatedInstance) {
    716         return new MockitoException(join(
    717                 "Mocked type must be the same as the type of your delegated instance.",
    718                 "Mocked type must be: " + delegatedInstance.getClass().getSimpleName() + ", but is: " + mockedType.getSimpleName(),
    719                 "  //correct delegate:",
    720                 "  spy = mock( ->List.class<- , withSettings().delegatedInstance( ->new ArrayList()<- );",
    721                 "  //incorrect - types don't match:",
    722                 "  spy = mock( ->List.class<- , withSettings().delegatedInstance( ->new HashSet()<- );"
    723         ));
    724     }
    725 
    726     public static MockitoException spyAndDelegateAreMutuallyExclusive() {
    727         return new MockitoException(join(
    728                 "Settings should not define a spy instance and a delegated instance at the same time."
    729         ));
    730     }
    731 
    732     public static MockitoException invalidArgumentRangeAtIdentityAnswerCreationTime() {
    733         return new MockitoException(join(
    734                 "Invalid argument index.",
    735                 "The index need to be a positive number that indicates the position of the argument to return.",
    736                 "However it is possible to use the -1 value to indicates that the last argument should be",
    737                 "returned."));
    738     }
    739 
    740     public static MockitoException invalidArgumentPositionRangeAtInvocationTime(InvocationOnMock invocation, boolean willReturnLastParameter, int argumentIndex) {
    741         return new MockitoException(join(
    742                 "Invalid argument index for the current invocation of method : ",
    743                 " -> " + safelyGetMockName(invocation.getMock()) + "." + invocation.getMethod().getName() + "()",
    744                 "",
    745                 (willReturnLastParameter ?
    746                         "Last parameter wanted" :
    747                         "Wanted parameter at position " + argumentIndex) + " but " + possibleArgumentTypesOf(invocation),
    748                 "The index need to be a positive number that indicates a valid position of the argument in the invocation.",
    749                 "However it is possible to use the -1 value to indicates that the last argument should be returned.",
    750                 ""
    751         ));
    752     }
    753 
    754     private static StringBuilder possibleArgumentTypesOf(InvocationOnMock invocation) {
    755         Class<?>[] parameterTypes = invocation.getMethod().getParameterTypes();
    756         if (parameterTypes.length == 0) {
    757             return new StringBuilder("the method has no arguments.\n");
    758         }
    759 
    760         StringBuilder stringBuilder = new StringBuilder("the possible argument indexes for this method are :\n");
    761         for (int i = 0, parameterTypesLength = parameterTypes.length; i < parameterTypesLength; i++) {
    762             stringBuilder.append("    [").append(i);
    763 
    764             if (invocation.getMethod().isVarArgs() && i == parameterTypesLength - 1) {
    765                 stringBuilder.append("+] ").append(parameterTypes[i].getComponentType().getSimpleName()).append("  <- Vararg").append("\n");
    766             } else {
    767                 stringBuilder.append("] ").append(parameterTypes[i].getSimpleName()).append("\n");
    768             }
    769         }
    770         return stringBuilder;
    771     }
    772 
    773     public static MockitoException wrongTypeOfArgumentToReturn(InvocationOnMock invocation, String expectedType, Class<?> actualType, int argumentIndex) {
    774         return new WrongTypeOfReturnValue(join(
    775                 "The argument of type '" + actualType.getSimpleName() + "' cannot be returned because the following ",
    776                 "method should return the type '" + expectedType + "'",
    777                 " -> " + safelyGetMockName(invocation.getMock()) + "." + invocation.getMethod().getName() + "()",
    778                 "",
    779                 "The reason for this error can be :",
    780                 "1. The wanted argument position is incorrect.",
    781                 "2. The answer is used on the wrong interaction.",
    782                 "",
    783                 "Position of the wanted argument is " + argumentIndex + " and " + possibleArgumentTypesOf(invocation),
    784                 "***",
    785                 "However if you're still unsure why you're getting above error read on.",
    786                 "Due to the nature of the syntax above problem might occur because:",
    787                 "1. This exception *might* occur in wrongly written multi-threaded tests.",
    788                 "   Please refer to Mockito FAQ on limitations of concurrency testing.",
    789                 "2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies - ",
    790                 "   - with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.",
    791                 ""
    792         ));
    793     }
    794 
    795     public static MockitoException defaultAnswerDoesNotAcceptNullParameter() {
    796         return new MockitoException("defaultAnswer() does not accept null parameter");
    797     }
    798 
    799     public static MockitoException serializableWontWorkForObjectsThatDontImplementSerializable(Class<?> classToMock) {
    800         return new MockitoException(join(
    801                 "You are using the setting 'withSettings().serializable()' however the type you are trying to mock '" + classToMock.getSimpleName() + "'",
    802                 "do not implement Serializable AND do not have a no-arg constructor.",
    803                 "This combination is requested, otherwise you will get an 'java.io.InvalidClassException' when the mock will be serialized",
    804                 "",
    805                 "Also note that as requested by the Java serialization specification, the whole hierarchy need to implements Serializable,",
    806                 "i.e. the top-most superclass has to implements Serializable.",
    807                 ""
    808         ));
    809     }
    810 
    811     public static MockitoException delegatedMethodHasWrongReturnType(Method mockMethod, Method delegateMethod, Object mock, Object delegate) {
    812         return new MockitoException(join(
    813                 "Methods called on delegated instance must have compatible return types with the mock.",
    814                 "When calling: " + mockMethod + " on mock: " + safelyGetMockName(mock),
    815                 "return type should be: " + mockMethod.getReturnType().getSimpleName() + ", but was: " + delegateMethod.getReturnType().getSimpleName(),
    816                 "Check that the instance passed to delegatesTo() is of the correct type or contains compatible methods",
    817                 "(delegate instance had type: " + delegate.getClass().getSimpleName() + ")"
    818         ));
    819     }
    820 
    821     public static MockitoException delegatedMethodDoesNotExistOnDelegate(Method mockMethod, Object mock, Object delegate) {
    822         return new MockitoException(join(
    823                 "Methods called on mock must exist in delegated instance.",
    824                 "When calling: " + mockMethod + " on mock: " + safelyGetMockName(mock),
    825                 "no such method was found.",
    826                 "Check that the instance passed to delegatesTo() is of the correct type or contains compatible methods",
    827                 "(delegate instance had type: " + delegate.getClass().getSimpleName() + ")"
    828         ));
    829     }
    830 
    831     public static MockitoException usingConstructorWithFancySerializable(SerializableMode mode) {
    832         return new MockitoException("Mocks instantiated with constructor cannot be combined with " + mode + " serialization mode.");
    833     }
    834 
    835     public static MockitoException cannotCreateTimerWithNegativeDurationTime(long durationMillis) {
    836         return new FriendlyReminderException(join(
    837                 "",
    838                 "Don't panic! I'm just a friendly reminder!",
    839                 "It is impossible for time to go backward, therefore...",
    840                 "You cannot put negative value of duration: (" + durationMillis + ")",
    841                 "as argument of timer methods (after(), timeout())",
    842                 ""
    843         ));
    844     }
    845 
    846     public static MockitoException notAnException() {
    847         return new MockitoException(join(
    848                 "Exception type cannot be null.",
    849                 "This may happen with doThrow(Class)|thenThrow(Class) family of methods if passing null parameter."));
    850     }
    851 
    852     private static MockName safelyGetMockName(Object mock) {
    853         return MockUtil.getMockName(mock);
    854     }
    855 
    856     public static UnnecessaryStubbingException formatUnncessaryStubbingException(Class<?> testClass, Collection<Invocation> unnecessaryStubbings) {
    857         StringBuilder stubbings = new StringBuilder();
    858         int count = 1;
    859         for (Invocation u : unnecessaryStubbings) {
    860             stubbings.append("\n  ").append(count++).append(". ").append(u.getLocation());
    861         }
    862         String heading = (testClass != null)?
    863                 "Unnecessary stubbings detected in test class: " + testClass.getSimpleName() :
    864                 "Unnecessary stubbings detected.";
    865 
    866         return new UnnecessaryStubbingException(join(
    867                 heading,
    868                 "Clean & maintainable test code requires zero unnecessary code.",
    869                 "Following stubbings are unnecessary (click to navigate to relevant line of code):" + stubbings,
    870                 "Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class."
    871         ));
    872     }
    873 
    874     public static void unncessaryStubbingException(List<Invocation> unused) {
    875         throw formatUnncessaryStubbingException(null, unused);
    876     }
    877 
    878     public static void potentialStubbingProblem(
    879             Invocation actualInvocation, Collection<Invocation> argMismatchStubbings) {
    880         StringBuilder stubbings = new StringBuilder();
    881         int count = 1;
    882         for (Invocation s : argMismatchStubbings) {
    883             stubbings.append("    ").append(count++).append(". ").append(s);
    884             stubbings.append("\n      ").append(s.getLocation()).append("\n");
    885         }
    886         stubbings.deleteCharAt(stubbings.length()-1); //remove trailing end of line
    887 
    888         throw new PotentialStubbingProblem(join(
    889                 "Strict stubbing argument mismatch. Please check:",
    890                 " - this invocation of '" + actualInvocation.getMethod().getName() + "' method:",
    891                 "    " + actualInvocation,
    892                 "    " + actualInvocation.getLocation(),
    893                 " - has following stubbing(s) with different arguments:",
    894                 stubbings,
    895                 "Typically, stubbing argument mismatch indicates user mistake when writing tests.",
    896                 "Mockito fails early so that you can debug potential problem easily.",
    897                 "However, there are legit scenarios when this exception generates false negative signal:",
    898                 "  - stubbing the same method multiple times using 'given().will()' or 'when().then()' API",
    899                 "    Please use 'will().given()' or 'doReturn().when()' API for stubbing.",
    900                 "  - stubbed method is intentionally invoked with different arguments by code under test",
    901                 "    Please use default or 'silent' JUnit Rule (equivalent of Strictness.LENIENT).",
    902                 "For more information see javadoc for PotentialStubbingProblem class."));
    903     }
    904 
    905     public static void redundantMockitoListener(String listenerType) {
    906         throw new RedundantListenerException(join(
    907             "Problems adding Mockito listener.",
    908             "Listener of type '" + listenerType + "' has already been added and not removed.",
    909             "It indicates that previous listener was not removed according to the API.",
    910             "When you add a listener, don't forget to remove the listener afterwards:",
    911             "  Mockito.framework().removeListener(myListener);",
    912             "For more information, see the javadoc for RedundantListenerException class."));
    913     }
    914 
    915     public static void unfinishedMockingSession() {
    916         throw new UnfinishedMockingSessionException(join(
    917                 "Unfinished mocking session detected.",
    918                 "Previous MockitoSession was not concluded with 'finishMocking()'.",
    919                 "For examples of correct usage see javadoc for MockitoSession class."));
    920     }
    921 }
    922