View Javadoc
1   package mockit;
2   
3   import static java.util.Arrays.asList;
4   
5   import static org.junit.jupiter.api.Assertions.assertEquals;
6   import static org.junit.jupiter.api.Assertions.assertFalse;
7   import static org.junit.jupiter.api.Assertions.assertSame;
8   import static org.junit.jupiter.api.Assertions.assertTrue;
9   
10  import java.util.Collections;
11  import java.util.List;
12  
13  import mockit.internal.expectations.invocation.MissingInvocation;
14  
15  import org.junit.Ignore;
16  import org.junit.Rule;
17  import org.junit.Test;
18  import org.junit.rules.ExpectedException;
19  
20  /**
21   * The Class ExpectationsWithVarArgsMatchersTest.
22   */
23  public final class ExpectationsWithVarArgsMatchersTest {
24  
25      /** The thrown. */
26      @Rule
27      public final ExpectedException thrown = ExpectedException.none();
28  
29      /**
30       * The Class Collaborator.
31       */
32      static class Collaborator {
33  
34          /**
35           * Complex operation.
36           *
37           * @param input1
38           *            the input 1
39           * @param otherInputs
40           *            the other inputs
41           *
42           * @return the list
43           */
44          List<?> complexOperation(Object input1, Object... otherInputs) {
45              return input1 == null ? Collections.emptyList() : asList(otherInputs);
46          }
47  
48          /**
49           * Another operation.
50           *
51           * @param i
52           *            the i
53           * @param b
54           *            the b
55           * @param s
56           *            the s
57           * @param otherStrings
58           *            the other strings
59           *
60           * @return the int
61           */
62          @SuppressWarnings("unused")
63          int anotherOperation(int i, boolean b, String s, String... otherStrings) {
64              return -1;
65          }
66  
67          /**
68           * Do something.
69           *
70           * @param i
71           *            the i
72           * @param values
73           *            the values
74           *
75           * @return true, if successful
76           */
77          static boolean doSomething(int i, Object... values) {
78              return i + values.length > 0;
79          }
80      }
81  
82      /**
83       * The Interface Dependency.
84       */
85      public interface Dependency {
86          /**
87           * Do something.
88           *
89           * @param args
90           *            the args
91           */
92          void doSomething(String... args);
93      }
94  
95      /** The mock. */
96      @Mocked
97      Collaborator mock;
98  
99      /** The mock 2. */
100     @Mocked
101     Dependency mock2;
102 
103     /**
104      * Replay varargs method with different than expected non varargs argument.
105      */
106     @Test
107     public void replayVarargsMethodWithDifferentThanExpectedNonVarargsArgument() {
108         thrown.expect(MissingInvocation.class);
109 
110         mock.complexOperation(2, 2, 3);
111 
112         new Verifications() {
113             {
114                 mock.complexOperation(1, 2, 3);
115             }
116         };
117     }
118 
119     /**
120      * Replay varargs method with different than expected number of varargs arguments.
121      */
122     @Test
123     public void replayVarargsMethodWithDifferentThanExpectedNumberOfVarargsArguments() {
124         new Expectations() {
125             {
126                 mock2.doSomething("1", "2", "3");
127                 times = 1;
128             }
129         };
130         thrown.expect(MissingInvocation.class);
131 
132         mock2.doSomething("1", "2");
133     }
134 
135     /**
136      * Replay varargs method with different than expected varargs argument.
137      */
138     @Test
139     public void replayVarargsMethodWithDifferentThanExpectedVarargsArgument() {
140         new Expectations() {
141             {
142                 mock2.doSomething("1", "2", "3");
143             }
144         };
145         thrown.expect(MissingInvocation.class);
146 
147         mock2.doSomething("1", "2", "4");
148     }
149 
150     /**
151      * Expect invocation on method with varargs argument using argument matchers.
152      */
153     @Test
154     public void expectInvocationOnMethodWithVarargsArgumentUsingArgumentMatchers() {
155         new Expectations() {
156             {
157                 mock.complexOperation(withEqual(1), withNotEqual(2), withNull());
158                 mock2.doSomething(withPrefix("C"), withSuffix("."));
159             }
160         };
161 
162         mock.complexOperation(1, 3, null);
163         mock2.doSomething("Cab", "123.");
164     }
165 
166     /**
167      * Expect invocation with any number of variable arguments.
168      */
169     @Test
170     public void expectInvocationWithAnyNumberOfVariableArguments() {
171         new Expectations() {
172             {
173                 mock.complexOperation(any, (Object[]) null);
174                 times = 3;
175                 mock2.doSomething((String[]) any);
176                 minTimes = 2;
177             }
178         };
179 
180         mock.complexOperation("test");
181         mock.complexOperation(null, 'X');
182         mock2.doSomething();
183         mock2.doSomething("test", "abc");
184         mock.complexOperation(123, true, "test", 3);
185     }
186 
187     /**
188      * Expect invocations with matcher for varargs parameter only.
189      */
190     @Test
191     public void expectInvocationsWithMatcherForVarargsParameterOnly() {
192         final List<Integer> values = asList(1, 2, 3);
193 
194         new Expectations() {
195             {
196                 mock.complexOperation("test", (Object[]) any);
197                 result = values;
198                 mock.anotherOperation(1, true, null, (String[]) any);
199                 result = 123;
200                 Collaborator.doSomething(anyInt, (Object[]) any);
201                 result = true;
202             }
203         };
204 
205         assertSame(values, mock.complexOperation("test", true, 'a', 2.5));
206         assertSame(values, mock.complexOperation("test", 123));
207         assertSame(values, mock.complexOperation("test"));
208 
209         assertEquals(123, mock.anotherOperation(1, true, null));
210         assertEquals(123, mock.anotherOperation(1, true, null, "A", null, "b"));
211         assertEquals(123, mock.anotherOperation(1, true, "test", "a", "b"));
212 
213         assertTrue(Collaborator.doSomething(-1));
214         assertTrue(Collaborator.doSomething(-2, "test"));
215     }
216 
217     /**
218      * Expect invocation on varargs method with matcher only for regular first parameter.
219      */
220     @Test
221     public void expectInvocationOnVarargsMethodWithMatcherOnlyForRegularFirstParameter() {
222         new Expectations() {
223             {
224                 mock.complexOperation(any, 1, 2);
225             }
226         };
227 
228         mock.complexOperation("test", 1, 2);
229     }
230 
231     /**
232      * Expect invocation with matchers for regular parameters and all varargs values.
233      */
234     @Test
235     public void expectInvocationWithMatchersForRegularParametersAndAllVarargsValues() {
236         new Expectations() {
237             {
238                 mock.complexOperation(anyBoolean, anyInt, withEqual(2));
239                 mock.complexOperation(anyString, withEqual(1), any, withEqual(3), anyBoolean);
240             }
241         };
242 
243         mock.complexOperation(true, 1, 2);
244         mock.complexOperation("abc", 1, 2, 3, true);
245     }
246 
247     /**
248      * Record expectations with matchers for some regular parameters and none for varargs.
249      */
250     @Test
251     public void recordExpectationsWithMatchersForSomeRegularParametersAndNoneForVarargs() {
252         new Expectations() {
253             {
254                 mock.anotherOperation(1, anyBoolean, "test", "a");
255                 result = 1;
256                 mock.anotherOperation(anyInt, true, withSubstring("X"), "a", "b");
257                 result = 2;
258             }
259         };
260 
261         // Invocations that match a recorded expectation:
262         assertEquals(1, mock.anotherOperation(1, true, "test", "a"));
263         assertEquals(1, mock.anotherOperation(1, true, "test", "a"));
264         assertEquals(1, mock.anotherOperation(1, false, "test", "a"));
265 
266         assertEquals(2, mock.anotherOperation(2, true, "aXb", "a", "b"));
267         assertEquals(2, mock.anotherOperation(-1, true, "  X", "a", "b"));
268         assertEquals(2, mock.anotherOperation(0, true, "XXX", "a", "b"));
269         assertEquals(2, mock.anotherOperation(1, true, "X", "a", "b"));
270 
271         // Invocations that don't match any expectation:
272         assertEquals(0, mock.anotherOperation(1, false, "test", null, "a"));
273         assertEquals(0, mock.anotherOperation(1, false, "tst", "a"));
274         assertEquals(0, mock.anotherOperation(0, false, "test", "a"));
275         assertEquals(0, mock.anotherOperation(1, true, "test", "b"));
276         assertEquals(0, mock.anotherOperation(1, true, "test"));
277 
278         assertEquals(0, mock.anotherOperation(2, false, "aXb", "a", "b"));
279         assertEquals(0, mock.anotherOperation(1, true, "  X", "A", "b"));
280         assertEquals(0, mock.anotherOperation(0, true, "XXX", "a"));
281         assertEquals(0, mock.anotherOperation(0, true, "XXX", "b"));
282         assertEquals(0, mock.anotherOperation(32, true, "-Xx", "a", null));
283     }
284 
285     /**
286      * Expect invocations with non null regular argument and any varargs.
287      */
288     @Test
289     public void expectInvocationsWithNonNullRegularArgumentAndAnyVarargs() {
290         new Expectations() {
291             {
292                 mock.complexOperation(withNotNull(), (Object[]) any);
293                 times = 3;
294             }
295         };
296 
297         mock.complexOperation(new Object(), 1, "2");
298         mock.complexOperation("", true, 'a', 2.5);
299         mock.complexOperation(123);
300     }
301 
302     /**
303      * Expect invocation with non null regular argument and any varargs but replay with null.
304      */
305     @Test
306     public void expectInvocationWithNonNullRegularArgumentAndAnyVarargsButReplayWithNull() {
307         thrown.expect(MissingInvocation.class);
308 
309         mock.complexOperation(null, 1, "2");
310 
311         new Verifications() {
312             {
313                 mock.complexOperation(withNotNull(), (Object[]) any);
314             }
315         };
316     }
317 
318     /**
319      * Expect invocation with matchers for some regular parameters and all for varargs.
320      */
321     @Test
322     public void expectInvocationWithMatchersForSomeRegularParametersAndAllForVarargs() {
323         new Expectations() {
324             {
325                 mock.anotherOperation(anyInt, true, withEqual("abc"), anyString, withEqual("test"));
326                 result = 1;
327                 mock.anotherOperation(0, anyBoolean, withEqual("Abc"), anyString, anyString, anyString);
328                 result = 2;
329             }
330         };
331 
332         assertEquals(0, mock.anotherOperation(1, false, "test", null, "a"));
333 
334         assertEquals(1, mock.anotherOperation(2, true, "abc", "xyz", "test"));
335         assertEquals(1, mock.anotherOperation(-1, true, "abc", null, "test"));
336         assertEquals(0, mock.anotherOperation(-1, true, "abc", null, "test", null));
337 
338         assertEquals(2, mock.anotherOperation(0, false, "Abc", "", "Abc", "test"));
339         assertEquals(0, mock.anotherOperation(0, false, "Abc", "", "Abc", "test", ""));
340     }
341 
342     /**
343      * The Class VarArgs.
344      */
345     @SuppressWarnings("unused")
346     static class VarArgs {
347 
348         /**
349          * Vars only.
350          *
351          * @param ints
352          *            the ints
353          */
354         public void varsOnly(int... ints) {
355         }
356 
357         /**
358          * Mixed.
359          *
360          * @param arg0
361          *            the arg 0
362          * @param ints
363          *            the ints
364          */
365         public void mixed(String arg0, int... ints) {
366         }
367     }
368 
369     /**
370      * Expect invocation with no var args.
371      *
372      * @param varargs
373      *            the varargs
374      */
375     @SuppressWarnings("NullArgumentToVariableArgMethod")
376     @Test
377     public void expectInvocationWithNoVarArgs(@Mocked final VarArgs varargs) {
378         new Expectations() {
379             {
380                 varargs.varsOnly();
381                 times = 2;
382                 varargs.mixed("arg");
383                 times = 2;
384             }
385         };
386 
387         varargs.varsOnly();
388         varargs.varsOnly(null);
389         varargs.mixed("arg");
390         varargs.mixed("arg", null);
391     }
392 
393     /**
394      * The Class ReferenceVarArgs.
395      */
396     static class ReferenceVarArgs {
397 
398         /**
399          * Mixed.
400          *
401          * @param strings
402          *            the strings
403          * @param ints
404          *            the ints
405          */
406         @SuppressWarnings("unused")
407         public void mixed(String[] strings, Integer... ints) {
408         }
409     }
410 
411     /**
412      * Expect invocation with non primitive var args.
413      *
414      * @param varargs
415      *            the varargs
416      */
417     @Test
418     public void expectInvocationWithNonPrimitiveVarArgs(@Mocked final ReferenceVarArgs varargs) {
419         final String[] strings1 = {};
420         final String[] strings2 = { "first", "second" };
421 
422         new Expectations() {
423             {
424                 varargs.mixed(null, 4, 5, 6);
425                 varargs.mixed(strings1, 4, 5, 6);
426                 varargs.mixed(strings2, 4, 5, 6);
427                 varargs.mixed(null);
428                 varargs.mixed(strings1);
429                 varargs.mixed(strings2);
430             }
431         };
432 
433         varargs.mixed(null, 4, 5, 6);
434         varargs.mixed(strings1, 4, 5, 6);
435         varargs.mixed(strings2, 4, 5, 6);
436         varargs.mixed(null);
437         varargs.mixed(strings1);
438         varargs.mixed(strings2);
439     }
440 
441     /**
442      * The Class PrimitiveVarArgs.
443      */
444     @SuppressWarnings("unused")
445     static class PrimitiveVarArgs {
446 
447         /**
448          * Vars only.
449          *
450          * @param ints
451          *            the ints
452          */
453         public void varsOnly(int... ints) {
454         }
455 
456         /**
457          * Mixed.
458          *
459          * @param arg0
460          *            the arg 0
461          * @param strings
462          *            the strings
463          * @param ints
464          *            the ints
465          */
466         public void mixed(String arg0, String[] strings, int... ints) {
467         }
468     }
469 
470     /**
471      * Expect invocation with primitive var args.
472      *
473      * @param varargs
474      *            the varargs
475      */
476     @SuppressWarnings("NullArgumentToVariableArgMethod")
477     @Test
478     public void expectInvocationWithPrimitiveVarArgs(@Mocked final PrimitiveVarArgs varargs) {
479         final String[] strings1 = {};
480         final String[] strings2 = { "first", "second" };
481 
482         new Expectations() {
483             {
484                 varargs.varsOnly(1, 2, 3);
485                 varargs.varsOnly(null);
486                 varargs.mixed("arg", null, 4, 5, 6);
487                 varargs.mixed("arg", strings1, 4, 5, 6);
488                 varargs.mixed("arg", strings2, 4, 5, 6);
489                 varargs.mixed("arg", null);
490                 varargs.mixed("arg", strings1);
491                 varargs.mixed("arg", strings2);
492                 varargs.mixed("arg", null, null);
493                 varargs.mixed(null, null, null);
494             }
495         };
496 
497         varargs.varsOnly(1, 2, 3);
498         varargs.varsOnly(null);
499         varargs.mixed("arg", null, 4, 5, 6);
500         varargs.mixed("arg", strings1, 4, 5, 6);
501         varargs.mixed("arg", strings2, 4, 5, 6);
502         varargs.mixed("arg", null);
503         varargs.mixed("arg", strings1);
504         varargs.mixed("arg", strings2);
505         varargs.mixed("arg", null, null);
506         varargs.mixed(null, null, null);
507     }
508 
509     /**
510      * The Class MixedVarArgs.
511      */
512     static class MixedVarArgs {
513         /**
514          * Mixed.
515          *
516          * @param strings
517          *            the strings
518          * @param ints
519          *            the ints
520          */
521         @SuppressWarnings("unused")
522         public void mixed(String[] strings, int... ints) {
523         }
524     }
525 
526     /**
527      * Expect invocation with primitive var args using matchers.
528      *
529      * @param varargs
530      *            the varargs
531      */
532     @Test
533     public void expectInvocationWithPrimitiveVarArgsUsingMatchers(@Mocked final MixedVarArgs varargs) {
534         final String[] strings1 = {};
535         final String[] strings2 = { "first", "second" };
536 
537         new Expectations() {
538             {
539                 varargs.mixed((String[]) withNull(), withEqual(4), withEqual(5), withEqual(6));
540                 varargs.mixed(withEqual(strings1), withEqual(4), withEqual(5), withEqual(6));
541                 varargs.mixed(withEqual(strings2), withEqual(4), withEqual(5), withEqual(6));
542                 varargs.mixed((String[]) withNull());
543                 varargs.mixed(withEqual(strings1));
544                 varargs.mixed(withEqual(strings2));
545             }
546         };
547 
548         varargs.mixed(null, 4, 5, 6);
549         varargs.mixed(strings1, 4, 5, 6);
550         varargs.mixed(strings2, 4, 5, 6);
551         varargs.mixed(null);
552         varargs.mixed(strings1);
553         varargs.mixed(strings2);
554     }
555 
556     /**
557      * Expect invocation with matchers for all parameters and varargs values but replay with different vararg value.
558      */
559     @Test
560     public void expectInvocationWithMatchersForAllParametersAndVarargsValuesButReplayWithDifferentVarargValue() {
561         thrown.expect(MissingInvocation.class);
562 
563         mock.complexOperation("abc", true, 1L);
564 
565         new Verifications() {
566             {
567                 mock.complexOperation(anyString, anyBoolean, withEqual(123L));
568             }
569         };
570     }
571 
572     /**
573      * Expectation recorded with not null matcher for varargs parameter.
574      */
575     @Test
576     public void expectationRecordedWithNotNullMatcherForVarargsParameter() {
577         new Expectations() {
578             {
579                 Collaborator.doSomething(0, (Object[]) withNotNull());
580                 result = true;
581             }
582         };
583 
584         assertTrue(Collaborator.doSomething(0, "test"));
585         // noinspection NullArgumentToVariableArgMethod
586         assertFalse(Collaborator.doSomething(0, (Object[]) null));
587     }
588 
589     /**
590      * Record varargs method with regular parameter using matcher for varargs only.
591      */
592     @Test
593     @Ignore("issue #292")
594     public void recordVarargsMethodWithRegularParameterUsingMatcherForVarargsOnly() {
595         new Expectations() {
596             {
597                 Collaborator.doSomething(123, anyString);
598             }
599         };
600 
601         Collaborator.doSomething(123, "test");
602     }
603 }