View Javadoc
1   /*
2    * MIT License
3    * Copyright (c) 2006-2025 JMockit developers
4    * See LICENSE file for full license text.
5    */
6   package mockit;
7   
8   import mockit.integration.junit5.JMockitExtension;
9   import mockit.internal.expectations.invocation.MissingInvocation;
10  import mockit.internal.expectations.invocation.UnexpectedInvocation;
11  
12  import org.junit.jupiter.api.Assertions;
13  import org.junit.jupiter.api.Test;
14  import org.junit.jupiter.api.extension.ExtendWith;
15  
16  /**
17   * The Class VerificationsInOrderTest.
18   */
19  @ExtendWith(JMockitExtension.class)
20  class VerificationsInOrderTest {
21  
22      /**
23       * The Class Dependency.
24       */
25      @SuppressWarnings("unused")
26      private static class Dependency {
27  
28          /**
29           * Sets the something.
30           *
31           * @param value
32           *            the new something
33           */
34          public void setSomething(int value) {
35          }
36  
37          /**
38           * Sets the something else.
39           *
40           * @param value
41           *            the new something else
42           */
43          public void setSomethingElse(String value) {
44          }
45  
46          /**
47           * Edits the A bunch more stuff.
48           */
49          public void editABunchMoreStuff() {
50          }
51  
52          /**
53           * Notify before save.
54           */
55          public void notifyBeforeSave() {
56          }
57  
58          /**
59           * Prepare.
60           */
61          public void prepare() {
62          }
63  
64          /**
65           * Save.
66           */
67          public void save() {
68          }
69  
70          /**
71           * Do something.
72           *
73           * @param h
74           *            the h
75           */
76          void doSomething(ClassWithHashCode h) {
77          }
78      }
79  
80      /**
81       * The Class ClassWithHashCode.
82       */
83      static final class ClassWithHashCode {
84          @Override
85          public boolean equals(Object obj) {
86              return obj instanceof ClassWithHashCode && this == obj;
87          }
88  
89          @Override
90          public int hashCode() {
91              return 123;
92          }
93      }
94  
95      /** The mock. */
96      @Mocked
97      Dependency mock;
98  
99      /**
100      * Exercise code under test.
101      */
102     private void exerciseCodeUnderTest() {
103         mock.prepare();
104         mock.setSomething(123);
105         mock.setSomethingElse("anotherValue");
106         mock.setSomething(45);
107         mock.editABunchMoreStuff();
108         mock.notifyBeforeSave();
109         mock.save();
110     }
111 
112     /**
113      * Verify simple invocations.
114      */
115     @Test
116     void verifySimpleInvocations() {
117         exerciseCodeUnderTest();
118 
119         new VerificationsInOrder() {
120             {
121                 mock.prepare();
122                 mock.setSomething(45);
123                 mock.editABunchMoreStuff();
124             }
125         };
126     }
127 
128     /**
129      * Verify unrecorded invocation that should happen but does not.
130      */
131     @Test
132     void verifyUnrecordedInvocationThatShouldHappenButDoesNot() {
133         Assertions.assertThrows(MissingInvocation.class, () -> {
134             mock.setSomething(1);
135 
136             new VerificationsInOrder() {
137                 {
138                     mock.notifyBeforeSave();
139                 }
140             };
141         });
142     }
143 
144     /**
145      * Verify unrecorded invocation that should happen exactly once but does not.
146      */
147     @Test
148     void verifyUnrecordedInvocationThatShouldHappenExactlyOnceButDoesNot() {
149         Throwable exception = Assertions.assertThrows(MissingInvocation.class, () -> {
150             mock.setSomething(1);
151 
152             new VerificationsInOrder() {
153                 {
154                     mock.setSomething(2);
155                     times = 1;
156                 }
157             };
158         });
159         Assertions.assertTrue(exception.getMessage().contains("2"));
160     }
161 
162     /**
163      * Verify recorded invocation that should happen but does not.
164      */
165     @Test
166     void verifyRecordedInvocationThatShouldHappenButDoesNot() {
167         new Expectations() {
168             {
169                 mock.setSomething(1);
170                 mock.notifyBeforeSave();
171                 // Prevent failure here, let the verification fail instead:
172                 minTimes = 0;
173             }
174         };
175 
176         mock.setSomething(1);
177 
178         MissingInvocation e = Assertions.assertThrows(MissingInvocation.class, () -> {
179             new VerificationsInOrder() {
180                 {
181                     mock.setSomething(1);
182                     mock.notifyBeforeSave();
183                 }
184             };
185         });
186     }
187 
188     /**
189      * Verify all invocations with some of them recorded.
190      */
191     @Test
192     void verifyAllInvocationsWithSomeOfThemRecorded() {
193         new Expectations() {
194             {
195                 mock.prepare();
196                 mock.editABunchMoreStuff();
197             }
198         };
199 
200         exerciseCodeUnderTest();
201 
202         new VerificationsInOrder() {
203             {
204                 mock.prepare();
205                 minTimes = 1;
206                 mock.setSomethingElse(anyString);
207                 mock.setSomething(anyInt);
208                 minTimes = 1;
209                 maxTimes = 2;
210                 mock.editABunchMoreStuff();
211                 mock.notifyBeforeSave();
212                 maxTimes = 1;
213                 mock.save();
214                 times = 1;
215             }
216         };
217     }
218 
219     /**
220      * Verify invocations with exact invocation counts having recorded matching expectation with argument matcher.
221      */
222     @Test
223     void verifyInvocationsWithExactInvocationCountsHavingRecordedMatchingExpectationWithArgumentMatcher() {
224         new Expectations() {
225             {
226                 mock.setSomething(anyInt);
227             }
228         };
229 
230         mock.setSomething(1);
231         mock.setSomething(2);
232 
233         new VerificationsInOrder() {
234             {
235                 mock.setSomething(1);
236                 times = 1;
237                 mock.setSomething(2);
238                 times = 1;
239             }
240         };
241     }
242 
243     /**
244      * Verify invocation that is allowed to happen any number of times and happens once.
245      */
246     @Test
247     void verifyInvocationThatIsAllowedToHappenAnyNumberOfTimesAndHappensOnce() {
248         mock.prepare();
249         mock.setSomething(123);
250         mock.save();
251 
252         new VerificationsInOrder() {
253             {
254                 mock.prepare();
255                 mock.setSomething(anyInt);
256                 mock.save();
257             }
258         };
259     }
260 
261     /**
262      * Verify simple invocations when out of order.
263      */
264     @Test
265     void verifySimpleInvocationsWhenOutOfOrder() {
266         Throwable exception = Assertions.assertThrows(MissingInvocation.class, () -> {
267             mock.setSomething(123);
268             mock.prepare();
269             new VerificationsInOrder() {
270                 {
271                     mock.prepare();
272                     mock.setSomething(123);
273                 }
274             };
275         });
276         Assertions.assertTrue(exception.getMessage().contains("123"));
277     }
278 
279     /**
280      * Verify repeating invocation.
281      */
282     @Test
283     void verifyRepeatingInvocation() {
284         mock.setSomething(123);
285         mock.setSomething(123);
286 
287         new VerificationsInOrder() {
288             {
289                 mock.setSomething(123);
290                 times = 2;
291             }
292         };
293     }
294 
295     /**
296      * Verify repeating invocation that occurs one time more than expected.
297      */
298     @Test
299     void verifyRepeatingInvocationThatOccursOneTimeMoreThanExpected() {
300         Assertions.assertThrows(UnexpectedInvocation.class, () -> {
301             mock.setSomething(123);
302             mock.setSomething(123);
303 
304             new VerificationsInOrder() {
305                 {
306                     mock.setSomething(123);
307                     maxTimes = 1;
308                 }
309             };
310         });
311     }
312 
313     /**
314      * Verify repeating invocation using matcher.
315      */
316     @Test
317     void verifyRepeatingInvocationUsingMatcher() {
318         mock.setSomething(123);
319         mock.setSomething(45);
320 
321         new VerificationsInOrder() {
322             {
323                 mock.setSomething(anyInt);
324                 times = 2;
325             }
326         };
327     }
328 
329     /**
330      * Verify invocation not expected to occur but which does.
331      */
332     @Test
333     void verifyInvocationNotExpectedToOccurButWhichDoes() {
334         Throwable exception = Assertions.assertThrows(UnexpectedInvocation.class, () -> {
335             mock.prepare();
336             mock.setSomething(123);
337 
338             new VerificationsInOrder() {
339                 {
340                     mock.prepare();
341                     mock.setSomething(anyInt);
342                     maxTimes = 0;
343                 }
344             };
345         });
346         Assertions.assertTrue(exception.getMessage().contains("123"));
347     }
348 
349     /**
350      * Verify with argument matcher.
351      */
352     @Test
353     void verifyWithArgumentMatcher() {
354         exerciseCodeUnderTest();
355 
356         new VerificationsInOrder() {
357             {
358                 mock.prepare();
359                 mock.setSomething(anyInt);
360             }
361         };
362     }
363 
364     /**
365      * Verify with individual invocation counts for non consecutive invocations.
366      */
367     @Test
368     void verifyWithIndividualInvocationCountsForNonConsecutiveInvocations() {
369         exerciseCodeUnderTest();
370 
371         new VerificationsInOrder() {
372             {
373                 mock.prepare();
374                 times = 1;
375                 mock.setSomething(anyInt);
376                 times = 2;
377             }
378         };
379     }
380 
381     /**
382      * Verify using invocation count constraint and argument matcher on object with mocked hash code.
383      *
384      * @param wh
385      *            the wh
386      */
387     @Test
388     void verifyUsingInvocationCountConstraintAndArgumentMatcherOnObjectWithMockedHashCode(
389             @Mocked ClassWithHashCode wh) {
390         mock.doSomething(null);
391         mock.doSomething(wh);
392 
393         new VerificationsInOrder() {
394             {
395                 mock.doSomething((ClassWithHashCode) withNull());
396                 times = 1;
397                 mock.doSomething((ClassWithHashCode) withNotNull());
398             }
399         };
400     }
401 
402     /**
403      * Verify with argument matchers when out of order.
404      */
405     @Test
406     void verifyWithArgumentMatchersWhenOutOfOrder() {
407         Throwable exception = Assertions.assertThrows(MissingInvocation.class, () -> {
408             mock.setSomething(123);
409             mock.setSomethingElse("anotherValue");
410             mock.setSomething(45);
411 
412             new VerificationsInOrder() {
413                 {
414                     mock.setSomething(anyInt);
415                     mock.setSomething(anyInt);
416                     mock.setSomethingElse(anyString);
417                 }
418             };
419         });
420         Assertions.assertTrue(exception.getMessage().contains("any String"));
421     }
422 
423     /**
424      * Verify with argument matcher and individual invocation count when out of order.
425      */
426     @Test
427     void verifyWithArgumentMatcherAndIndividualInvocationCountWhenOutOfOrder() {
428         Throwable exception = Assertions.assertThrows(MissingInvocation.class, () -> {
429             mock.setSomething(123);
430             mock.prepare();
431             mock.setSomething(45);
432 
433             new VerificationsInOrder() {
434                 {
435                     mock.prepare();
436                     mock.setSomething(anyInt);
437                     times = 2;
438                 }
439             };
440         });
441         Assertions.assertTrue(
442                 exception.getMessage().contains("Missing 1 invocation") && exception.getMessage().contains("any int"));
443     }
444 
445     /**
446      * Verify two independent sequences of invocations which occur separately.
447      */
448     @Test
449     void verifyTwoIndependentSequencesOfInvocationsWhichOccurSeparately() {
450         // First sequence:
451         mock.setSomething(1);
452         mock.setSomething(2);
453 
454         // Second sequence:
455         mock.setSomething(10);
456         mock.setSomething(20);
457 
458         // Verifies first sequence:
459         new VerificationsInOrder() {
460             {
461                 mock.setSomething(1);
462                 mock.setSomething(2);
463             }
464         };
465 
466         // Verifies second sequence:
467         new VerificationsInOrder() {
468             {
469                 mock.setSomething(10);
470                 mock.setSomething(20);
471             }
472         };
473     }
474 
475     /**
476      * Verify two independent sequences of invocations which are mixed together.
477      */
478     @Test
479     void verifyTwoIndependentSequencesOfInvocationsWhichAreMixedTogether() {
480         mock.setSomething(1); // first sequence
481         mock.setSomething(10); // second sequence
482         mock.setSomething(2); // first sequence
483         mock.setSomething(20); // second sequence
484 
485         // Verifies second sequence:
486         new VerificationsInOrder() {
487             {
488                 mock.setSomething(10);
489                 mock.setSomething(20);
490             }
491         };
492 
493         // Verifies first sequence:
494         new VerificationsInOrder() {
495             {
496                 mock.setSomething(1);
497                 mock.setSomething(2);
498             }
499         };
500     }
501 
502     /**
503      * Verify second sequence of invocations with times constraint after verifying last invocation of first sequence.
504      */
505     @Test
506     void verifySecondSequenceOfInvocationsWithTimesConstraintAfterVerifyingLastInvocationOfFirstSequence() {
507         mock.setSomething(1); // first sequence
508         mock.setSomething(3); // second sequence
509         mock.setSomething(4); // second sequence
510         mock.setSomething(2); // first sequence
511 
512         new VerificationsInOrder() {
513             {
514                 mock.setSomething(1);
515                 mock.setSomething(2);
516             }
517         };
518 
519         new VerificationsInOrder() {
520             {
521                 mock.setSomething(3);
522                 mock.setSomething(4);
523                 times = 1;
524             }
525         };
526     }
527 }