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