1/*
2 * Copyright (c) 2007 Mockito contributors
3 * This program is made available under the terms of the MIT License.
4 */
5
6package org.mockito.exceptions;
7
8import org.mockito.exceptions.base.MockitoAssertionError;
9import org.mockito.exceptions.base.MockitoException;
10import org.mockito.exceptions.misusing.*;
11import org.mockito.exceptions.verification.*;
12import org.mockito.internal.debugging.LocationImpl;
13import org.mockito.internal.exceptions.VerificationAwareInvocation;
14import org.mockito.internal.exceptions.util.ScenarioPrinter;
15import org.mockito.internal.junit.JUnitTool;
16import org.mockito.internal.matchers.LocalizedMatcher;
17import org.mockito.internal.util.MockUtil;
18import org.mockito.internal.util.StringJoiner;
19import org.mockito.invocation.DescribedInvocation;
20import org.mockito.invocation.Invocation;
21import org.mockito.invocation.InvocationOnMock;
22import org.mockito.invocation.Location;
23import org.mockito.listeners.InvocationListener;
24
25import java.lang.reflect.Field;
26import java.util.ArrayList;
27import java.util.Collection;
28import java.util.List;
29
30import static org.mockito.internal.reporting.Pluralizer.pluralize;
31import 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 */
44public 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