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