View Javadoc
1   package mockit;
2   
3   import static org.junit.jupiter.api.Assertions.assertEquals;
4   import static org.junit.jupiter.api.Assertions.assertNotNull;
5   import static org.junit.jupiter.api.Assertions.assertTrue;
6   
7   import java.lang.reflect.Method;
8   
9   import mockit.internal.expectations.invocation.MissingInvocation;
10  import mockit.internal.expectations.invocation.UnexpectedInvocation;
11  
12  import org.junit.Ignore;
13  import org.junit.Rule;
14  import org.junit.Test;
15  import org.junit.rules.ExpectedException;
16  
17  /**
18   * The Class ExpectationsTest.
19   */
20  @SuppressWarnings({ "unused", "ParameterHidesMemberVariable" })
21  public final class ExpectationsTest {
22  
23      /** The thrown. */
24      @Rule
25      public final ExpectedException thrown = ExpectedException.none();
26  
27      /**
28       * The Class Dependency.
29       */
30      @Deprecated
31      public static class Dependency {
32  
33          /** The value. */
34          @Deprecated
35          int value;
36  
37          /**
38           * Instantiates a new dependency.
39           */
40          @Deprecated
41          public Dependency() {
42              value = -1;
43          }
44  
45          /**
46           * Sets the something.
47           *
48           * @param value
49           *            the new something
50           */
51          @Ignore("test")
52          public void setSomething(@Deprecated int value) {
53          }
54  
55          /**
56           * Sets the something else.
57           *
58           * @param value
59           *            the new something else
60           */
61          public void setSomethingElse(String value) {
62          }
63  
64          /**
65           * Do something.
66           *
67           * @param i
68           *            the i
69           * @param b
70           *            the b
71           *
72           * @return the int
73           */
74          public int doSomething(Integer i, boolean b) {
75              return i;
76          }
77  
78          /**
79           * Edits the A bunch more stuff.
80           *
81           * @return the int
82           */
83          public int editABunchMoreStuff() {
84              return 1;
85          }
86  
87          /**
88           * Notify before save.
89           *
90           * @return true, if successful
91           */
92          public boolean notifyBeforeSave() {
93              return true;
94          }
95  
96          /**
97           * Prepare.
98           */
99          public void prepare() {
100         }
101 
102         /**
103          * Save.
104          */
105         public void save() {
106         }
107 
108         /**
109          * Static method.
110          *
111          * @param o
112          *            the o
113          * @param e
114          *            the e
115          *
116          * @return the int
117          */
118         static int staticMethod(Object o, Exception e) {
119             return -1;
120         }
121     }
122 
123     /** The mock. */
124     @Mocked
125     Dependency mock;
126 
127     /**
128      * Exercise code under test.
129      */
130     void exerciseCodeUnderTest() {
131         mock.prepare();
132         mock.setSomething(123);
133         mock.setSomethingElse("anotherValue");
134         mock.setSomething(45);
135         mock.editABunchMoreStuff();
136         mock.notifyBeforeSave();
137         mock.save();
138     }
139 
140     /**
141      * Record simple invocations.
142      */
143     @Test
144     public void recordSimpleInvocations() {
145         new Expectations() {
146             {
147                 mock.prepare();
148                 mock.editABunchMoreStuff();
149                 mock.setSomething(45);
150             }
151         };
152 
153         exerciseCodeUnderTest();
154     }
155 
156     /**
157      * Record invocation that will not occur.
158      */
159     @Test
160     public void recordInvocationThatWillNotOccur() {
161         new Expectations() {
162             {
163                 mock.editABunchMoreStuff();
164                 result = 123;
165                 times = 0;
166             }
167         };
168 
169         mock.setSomething(123);
170         mock.prepare();
171     }
172 
173     /**
174      * Expectations recorded on same method with same matchers but different arguments.
175      */
176     @Test
177     public void expectationsRecordedOnSameMethodWithSameMatchersButDifferentArguments() {
178         new Expectations() {
179             {
180                 mock.doSomething(1, anyBoolean);
181                 result = 1;
182                 mock.doSomething(2, anyBoolean);
183                 result = 2;
184             }
185         };
186 
187         assertEquals(1, mock.doSomething(1, true));
188         assertEquals(2, mock.doSomething(2, false));
189         assertEquals(0, mock.doSomething(3, false));
190     }
191 
192     /**
193      * Expectations recorded on same method with matcher in one and fixed argument in another.
194      */
195     @Test
196     public void expectationsRecordedOnSameMethodWithMatcherInOneAndFixedArgumentInAnother() {
197         new Expectations() {
198             {
199                 mock.doSomething(1, anyBoolean);
200                 result = 1;
201                 mock.doSomething(anyInt, anyBoolean);
202                 result = 2;
203             }
204         };
205 
206         assertEquals(1, mock.doSomething(1, true));
207         assertEquals(2, mock.doSomething(null, false));
208         assertEquals(2, mock.doSomething(2, true));
209         assertEquals(1, mock.doSomething(1, false));
210     }
211 
212     /**
213      * Record invocation with exact expected number of invocations but fail to satisfy.
214      */
215     @Test(expected = MissingInvocation.class)
216     public void recordInvocationWithExactExpectedNumberOfInvocationsButFailToSatisfy() {
217         new Expectations() {
218             {
219                 mock.editABunchMoreStuff();
220                 times = 1;
221             }
222         };
223     }
224 
225     /**
226      * Record invocation with minimum expected number of invocations but fail to satisfy.
227      */
228     @Test(expected = MissingInvocation.class)
229     public void recordInvocationWithMinimumExpectedNumberOfInvocationsButFailToSatisfy() {
230         new Expectations() {
231             {
232                 mock.editABunchMoreStuff();
233                 minTimes = 2;
234             }
235         };
236 
237         mock.editABunchMoreStuff();
238     }
239 
240     /**
241      * Record invocation with maximum expected number of invocations but fail to satisfy.
242      */
243     @Test(expected = UnexpectedInvocation.class)
244     public void recordInvocationWithMaximumExpectedNumberOfInvocationsButFailToSatisfy() {
245         new Expectations() {
246             {
247                 mock.editABunchMoreStuff();
248                 maxTimes = 1;
249             }
250         };
251 
252         mock.editABunchMoreStuff();
253         mock.editABunchMoreStuff();
254     }
255 
256     /**
257      * Record invocations with expected invocation counts.
258      */
259     @Test
260     public void recordInvocationsWithExpectedInvocationCounts() {
261         new Expectations() {
262             {
263                 mock.setSomethingElse(anyString);
264                 minTimes = 1;
265                 mock.save();
266                 times = 2;
267             }
268         };
269 
270         mock.setSomething(3);
271         mock.save();
272         mock.setSomethingElse("test");
273         mock.save();
274     }
275 
276     /**
277      * Record invocations with min invocation count larger than will occur.
278      */
279     @Test(expected = MissingInvocation.class)
280     public void recordInvocationsWithMinInvocationCountLargerThanWillOccur() {
281         new Expectations() {
282             {
283                 mock.save();
284                 minTimes = 2;
285             }
286         };
287 
288         mock.save();
289     }
290 
291     /**
292      * Record with argument matcher and individual invocation counts.
293      */
294     @Test
295     public void recordWithArgumentMatcherAndIndividualInvocationCounts() {
296         new Expectations() {
297             {
298                 mock.prepare();
299                 maxTimes = 1;
300                 mock.setSomething(anyInt);
301                 minTimes = 2;
302                 mock.editABunchMoreStuff();
303                 maxTimes = 5;
304                 mock.save();
305                 times = 1;
306             }
307         };
308 
309         exerciseCodeUnderTest();
310     }
311 
312     /**
313      * Record with max invocation count followed by return value.
314      */
315     @Test
316     public void recordWithMaxInvocationCountFollowedByReturnValue() {
317         new Expectations() {
318             {
319                 Dependency.staticMethod(any, null);
320                 maxTimes = 1;
321                 result = 1;
322             }
323         };
324 
325         assertEquals(1, Dependency.staticMethod(new Object(), new Exception()));
326     }
327 
328     /**
329      * Record with max invocation count followed by return value but replay one time beyond max.
330      */
331     @Test(expected = UnexpectedInvocation.class)
332     public void recordWithMaxInvocationCountFollowedByReturnValueButReplayOneTimeBeyondMax() {
333         new Expectations() {
334             {
335                 Dependency.staticMethod(any, null);
336                 maxTimes = 1;
337                 result = 1;
338             }
339         };
340 
341         Dependency.staticMethod(null, null);
342         Dependency.staticMethod(null, null);
343     }
344 
345     /**
346      * Record with return value followed by expected invocation count.
347      */
348     @Test
349     public void recordWithReturnValueFollowedByExpectedInvocationCount() {
350         new Expectations() {
351             {
352                 Dependency.staticMethod(any, null);
353                 result = 1;
354                 times = 1;
355             }
356         };
357 
358         assertEquals(1, Dependency.staticMethod(null, null));
359     }
360 
361     /**
362      * Record with min invocation count followed by return value using delegate.
363      */
364     @Test
365     public void recordWithMinInvocationCountFollowedByReturnValueUsingDelegate() {
366         new Expectations() {
367             {
368                 Dependency.staticMethod(any, null);
369                 minTimes = 1;
370                 result = new Delegate<Object>() {
371                     int staticMethod(Object o, Exception e) {
372                         return 1;
373                     }
374                 };
375             }
376         };
377 
378         assertEquals(1, Dependency.staticMethod(null, null));
379     }
380 
381     /**
382      * Mocked class with annotated elements.
383      *
384      * @throws Exception
385      *             the exception
386      */
387     @Test
388     public void mockedClassWithAnnotatedElements() throws Exception {
389         Class<?> mockedClass = mock.getClass();
390         assertTrue(mockedClass.isAnnotationPresent(Deprecated.class));
391         assertTrue(mockedClass.getDeclaredField("value").isAnnotationPresent(Deprecated.class));
392         assertTrue(mockedClass.getDeclaredConstructor().isAnnotationPresent(Deprecated.class));
393 
394         Method mockedMethod = mockedClass.getDeclaredMethod("setSomething", int.class);
395         Ignore ignore = mockedMethod.getAnnotation(Ignore.class);
396         assertNotNull(ignore);
397         assertEquals("test", ignore.value());
398         assertTrue(mockedMethod.getParameterAnnotations()[0][0] instanceof Deprecated);
399     }
400 
401     /**
402      * The Class Collaborator.
403      */
404     static class Collaborator {
405 
406         /** The value. */
407         private int value;
408 
409         /**
410          * Gets the value.
411          *
412          * @return the value
413          */
414         int getValue() {
415             return value;
416         }
417 
418         /**
419          * Sets the value.
420          *
421          * @param value
422          *            the new value
423          */
424         void setValue(int value) {
425             this.value = value;
426         }
427 
428         /**
429          * Provide some service.
430          */
431         void provideSomeService() {
432         }
433 
434         /**
435          * Do something.
436          *
437          * @param s
438          *            the s
439          *
440          * @return the string
441          */
442         String doSomething(String s) {
443             return s.toLowerCase();
444         }
445 
446         /**
447          * Do internal.
448          *
449          * @return the string
450          */
451         static String doInternal() {
452             return "123";
453         }
454     }
455 
456     /**
457      * Expect only one invocation but exercise others during replay.
458      *
459      * @param mock
460      *            the mock
461      */
462     @Test
463     public void expectOnlyOneInvocationButExerciseOthersDuringReplay(@Mocked final Collaborator mock) {
464         thrown.expect(UnexpectedInvocation.class);
465         new Expectations() {
466             {
467                 mock.provideSomeService();
468             }
469         };
470 
471         mock.provideSomeService();
472         mock.setValue(1);
473 
474         new FullVerifications() {
475         };
476     }
477 
478     /**
479      * Expect nothing on mocked type but exercise it during replay.
480      *
481      * @param mock
482      *            the mock
483      */
484     @Test
485     public void expectNothingOnMockedTypeButExerciseItDuringReplay(@Mocked final Collaborator mock) {
486         thrown.expect(UnexpectedInvocation.class);
487         new Expectations() {
488             {
489                 mock.setValue(anyInt);
490                 times = 0;
491             }
492         };
493 
494         mock.setValue(2);
495 
496         new FullVerifications() {
497         };
498     }
499 
500     /**
501      * Replay with unexpected static method invocation.
502      *
503      * @param mock
504      *            the mock
505      */
506     @Test
507     public void replayWithUnexpectedStaticMethodInvocation(@Mocked final Collaborator mock) {
508         thrown.expect(UnexpectedInvocation.class);
509         new Expectations() {
510             {
511                 mock.getValue();
512             }
513         };
514 
515         Collaborator.doInternal();
516 
517         new FullVerifications() {
518         };
519     }
520 
521     /**
522      * Failure from unexpected invocation in another thread.
523      *
524      * @param mock
525      *            the mock
526      *
527      * @throws Exception
528      *             the exception
529      */
530     @Test
531     public void failureFromUnexpectedInvocationInAnotherThread(@Mocked final Collaborator mock) throws Exception {
532         Thread t = new Thread() {
533             @Override
534             public void run() {
535                 mock.provideSomeService();
536             }
537         };
538 
539         new Expectations() {
540             {
541                 mock.getValue();
542             }
543         };
544         thrown.expect(UnexpectedInvocation.class);
545 
546         mock.getValue();
547         t.start();
548         t.join();
549 
550         new FullVerifications() {
551         };
552     }
553 
554     /**
555      * Recording expectation on method with one argument but replaying with another should produce useful error message.
556      *
557      * @param mock
558      *            the mock
559      */
560     @Test
561     public void recordingExpectationOnMethodWithOneArgumentButReplayingWithAnotherShouldProduceUsefulErrorMessage(
562             @Mocked final Collaborator mock) {
563         final String expected = "expected";
564         new Expectations() {
565             {
566                 mock.doSomething(expected);
567             }
568         };
569 
570         mock.doSomething(expected);
571 
572         String another = "another";
573         mock.doSomething(another);
574 
575         thrown.expect(UnexpectedInvocation.class);
576         thrown.expectMessage(another);
577         new FullVerifications() {
578         };
579     }
580 }