View Javadoc
1   package mockit;
2   
3   import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4   import static org.junit.jupiter.api.Assertions.assertEquals;
5   import static org.junit.jupiter.api.Assertions.assertFalse;
6   import static org.junit.jupiter.api.Assertions.assertNull;
7   import static org.junit.jupiter.api.Assertions.assertSame;
8   import static org.junit.jupiter.api.Assertions.assertThrows;
9   import static org.junit.jupiter.api.Assertions.assertTrue;
10  import static org.junit.jupiter.api.Assertions.fail;
11  
12  import java.util.ArrayList;
13  import java.util.Collection;
14  import java.util.List;
15  
16  import org.junit.Rule;
17  import org.junit.Test;
18  import org.junit.rules.ExpectedException;
19  
20  /**
21   * The Class DelegateTest.
22   */
23  @SuppressWarnings("unused")
24  public final class DelegateTest {
25  
26      /** The thrown. */
27      @Rule
28      public final ExpectedException thrown = ExpectedException.none();
29  
30      /**
31       * The Class Collaborator.
32       */
33      static class Collaborator {
34  
35          /**
36           * Instantiates a new collaborator.
37           */
38          Collaborator() {
39          }
40  
41          /**
42           * Instantiates a new collaborator.
43           *
44           * @param i
45           *            the i
46           */
47          Collaborator(int i) {
48          }
49  
50          /**
51           * Gets the value.
52           *
53           * @return the value
54           */
55          int getValue() {
56              return -1;
57          }
58  
59          /**
60           * Do something.
61           *
62           * @param b
63           *            the b
64           * @param i
65           *            the i
66           * @param s
67           *            the s
68           *
69           * @return the string
70           */
71          String doSomething(boolean b, int[] i, String s) {
72              return s + b + i[0];
73          }
74  
75          /**
76           * Static method.
77           *
78           * @return true, if successful
79           */
80          static boolean staticMethod() {
81              return true;
82          }
83  
84          /**
85           * Static method.
86           *
87           * @param i
88           *            the i
89           *
90           * @return true, if successful
91           */
92          static boolean staticMethod(int i) {
93              return i > 0;
94          }
95  
96          /**
97           * Native method.
98           *
99           * @param b
100          *            the b
101          *
102          * @return the long
103          */
104         protected native long nativeMethod(boolean b);
105 
106         /**
107          * Native method returning an array of A primitive type.
108          *
109          * @return the int[]
110          */
111         public native int[] nativeMethodReturningAnArrayOfAPrimitiveType();
112 
113         /**
114          * Native method returning an array of A reference type.
115          *
116          * @return the foo[]
117          */
118         public native Foo[] nativeMethodReturningAnArrayOfAReferenceType();
119 
120         /**
121          * Native method returning A two dimensional array.
122          *
123          * @return the string[][]
124          */
125         public native String[][] nativeMethodReturningATwoDimensionalArray();
126 
127         /**
128          * Final method.
129          *
130          * @return the char
131          */
132         final char finalMethod() {
133             return 's';
134         }
135 
136         /**
137          * Adds the elements.
138          *
139          * @param elements
140          *            the elements
141          */
142         void addElements(List<String> elements) {
143             elements.add("one element");
144         }
145 
146         /**
147          * Gets the foo.
148          *
149          * @return the foo
150          */
151         Foo getFoo() {
152             return null;
153         }
154 
155         /**
156          * Gets the array.
157          *
158          * @return the array
159          */
160         byte[] getArray() {
161             return null;
162         }
163     }
164 
165     /**
166      * The Class Foo.
167      */
168     static final class Foo {
169         /**
170          * Do something.
171          *
172          * @return the int
173          */
174         int doSomething() {
175             return 1;
176         }
177     }
178 
179     /**
180      * Result from delegate.
181      *
182      * @param collaborator
183      *            the collaborator
184      */
185     @Test
186     public void resultFromDelegate(@Mocked final Collaborator collaborator) {
187         final boolean bExpected = true;
188         final int[] iExpected = {};
189         final String sExpected = "test";
190 
191         new Expectations() {
192             {
193                 collaborator.getValue();
194                 result = new Delegate<Object>() {
195                     int getValue() {
196                         return 2;
197                     }
198                 };
199 
200                 collaborator.doSomething(bExpected, iExpected, sExpected);
201                 result = new Delegate<Object>() {
202                     String doSomething(boolean b, int[] i, String s) {
203                         assertEquals(bExpected, b);
204                         assertArrayEquals(iExpected, i);
205                         assertEquals(sExpected, s);
206                         return "";
207                     }
208                 };
209             }
210         };
211 
212         assertEquals(2, collaborator.getValue());
213         assertEquals("", collaborator.doSomething(bExpected, iExpected, sExpected));
214     }
215 
216     /**
217      * Consecutive results through delegates having different values.
218      *
219      * @param mock
220      *            the mock
221      */
222     @Test
223     public void consecutiveResultsThroughDelegatesHavingDifferentValues(@Mocked final Collaborator mock) {
224         new Expectations() {
225             {
226                 mock.getValue();
227                 result = new Delegate<Object>() {
228                     int getValue() {
229                         return 1;
230                     }
231                 };
232                 result = new Delegate<Object>() {
233                     int getValue() {
234                         return 2;
235                     }
236                 };
237             }
238         };
239 
240         Collaborator collaborator = new Collaborator();
241         assertEquals(1, collaborator.getValue());
242         assertEquals(2, collaborator.getValue());
243     }
244 
245     /**
246      * Consecutive return values through delegates using single returns with varargs.
247      *
248      * @param collaborator
249      *            the collaborator
250      */
251     @Test
252     public void consecutiveReturnValuesThroughDelegatesUsingSingleReturnsWithVarargs(
253             @Mocked final Collaborator collaborator) {
254         final int[] array = { 1, 2 };
255 
256         new Expectations() {
257             {
258                 collaborator.doSomething(true, array, "");
259                 returns(new Delegate<Object>() {
260                     String execute(boolean b, int[] i, String s) {
261                         assertEquals(1, i[0]);
262                         return "a";
263                     }
264                 }, new Delegate<Object>() {
265                     String execute(boolean b, int[] i, String s) {
266                         assertEquals(2, i[0]);
267                         return "b";
268                     }
269                 });
270             }
271         };
272 
273         assertEquals("a", collaborator.doSomething(true, array, ""));
274 
275         array[0] = 2;
276         assertEquals("b", collaborator.doSomething(true, array, ""));
277     }
278 
279     /**
280      * Result with multiple return values through single delegate.
281      *
282      * @param collaborator
283      *            the collaborator
284      */
285     @Test
286     public void resultWithMultipleReturnValuesThroughSingleDelegate(@Mocked final Collaborator collaborator) {
287         new Expectations() {
288             {
289                 collaborator.getValue();
290                 result = new Delegate<Object>() {
291                     int i = 1;
292 
293                     int getValue() {
294                         return i++;
295                     }
296                 };
297             }
298         };
299 
300         assertEquals(1, collaborator.getValue());
301         assertEquals(2, collaborator.getValue());
302         assertEquals(3, collaborator.getValue());
303     }
304 
305     /**
306      * Constructor delegate with single method.
307      *
308      * @param mock
309      *            the mock
310      */
311     @Test
312     public void constructorDelegateWithSingleMethod(@Mocked Collaborator mock) {
313         final ConstructorDelegate delegate = new ConstructorDelegate();
314 
315         new Expectations() {
316             {
317                 new Collaborator(anyInt);
318                 result = delegate;
319             }
320         };
321 
322         new Collaborator(4);
323 
324         assertTrue(delegate.capturedArgument > 0);
325     }
326 
327     /**
328      * The Class ConstructorDelegate.
329      */
330     static class ConstructorDelegate implements Delegate<Void> {
331 
332         /** The captured argument. */
333         int capturedArgument;
334 
335         /**
336          * Delegate.
337          *
338          * @param i
339          *            the i
340          */
341         void delegate(int i) {
342             capturedArgument = i;
343         }
344     }
345 
346     /**
347      * Constructor delegate with multiple methods.
348      *
349      * @param mock
350      *            the mock
351      */
352     @Test
353     public void constructorDelegateWithMultipleMethods(@Mocked Collaborator mock) {
354         new Expectations() {
355             {
356                 new Collaborator(anyInt);
357                 result = new Delegate<Object>() {
358                     void init(int i) {
359                         if (i < 0)
360                             throw new IllegalArgumentException();
361                     }
362 
363                     private void anotherMethod() {
364                     }
365                 };
366             }
367         };
368 
369         new Collaborator(123);
370 
371         try {
372             new Collaborator(-123);
373             fail();
374         } catch (IllegalArgumentException ignore) {
375         }
376     }
377 
378     /**
379      * Attempt to use constructor delegate with private methods only.
380      *
381      * @param mock
382      *            the mock
383      */
384     @Test
385     public void attemptToUseConstructorDelegateWithPrivateMethodsOnly(@Mocked Collaborator mock) {
386         thrown.expect(IllegalArgumentException.class);
387         thrown.expectMessage("No non-private instance method found");
388 
389         new Expectations() {
390             {
391                 new Collaborator();
392                 result = new Delegate<Object>() {
393                     private void delegate() {
394                     }
395 
396                     private void anotherMethod() {
397                     }
398                 };
399             }
400         };
401     }
402 
403     /**
404      * Delegate for static method.
405      *
406      * @param unused
407      *            the unused
408      */
409     @Test
410     public void delegateForStaticMethod(@Mocked Collaborator unused) {
411         new Expectations() {
412             {
413                 Collaborator.staticMethod();
414                 result = new Delegate<Object>() {
415                     boolean staticMethod() {
416                         return false;
417                     }
418                 };
419             }
420         };
421 
422         assertFalse(Collaborator.staticMethod());
423     }
424 
425     /**
426      * Delegate with static method.
427      *
428      * @param mock
429      *            the mock
430      */
431     @Test
432     public void delegateWithStaticMethod(@Mocked Collaborator mock) {
433         new Expectations() {
434             {
435                 Collaborator.staticMethod(anyInt);
436                 result = StaticDelegate.create();
437             }
438         };
439 
440         assertTrue(Collaborator.staticMethod(34));
441     }
442 
443     /**
444      * The Class StaticDelegate.
445      */
446     static final class StaticDelegate implements Delegate<Object> {
447 
448         /**
449          * Creates the.
450          *
451          * @return the static delegate
452          */
453         static StaticDelegate create() {
454             return new StaticDelegate();
455         }
456 
457         /**
458          * Delegate method.
459          *
460          * @param i
461          *            the i
462          *
463          * @return true, if successful
464          */
465         boolean delegateMethod(int i) {
466             assertEquals(34, i);
467             return true;
468         }
469     }
470 
471     /**
472      * Delegate for native method.
473      *
474      * @param mock
475      *            the mock
476      */
477     @Test
478     public void delegateForNativeMethod(@Mocked final Collaborator mock) {
479         new Expectations() {
480             {
481                 mock.nativeMethod(anyBoolean);
482                 result = new Delegate<Object>() {
483                     Long nativeMethod(boolean b) {
484                         assertTrue(b);
485                         return 0L;
486                     }
487                 };
488             }
489         };
490 
491         assertEquals(0L, new Collaborator().nativeMethod(true));
492     }
493 
494     /**
495      * Delegate for final method.
496      *
497      * @param mock
498      *            the mock
499      */
500     @Test
501     public void delegateForFinalMethod(@Mocked final Collaborator mock) {
502         new Expectations() {
503             {
504                 mock.finalMethod();
505                 result = new Delegate<Object>() {
506                     char finalMethod() {
507                         return 'M';
508                     }
509                 };
510             }
511         };
512 
513         assertEquals('M', new Collaborator().finalMethod());
514     }
515 
516     /**
517      * Delegate for method with compatible but distinct parameter type.
518      *
519      * @param collaborator
520      *            the collaborator
521      */
522     @Test
523     public void delegateForMethodWithCompatibleButDistinctParameterType(@Mocked final Collaborator collaborator) {
524         new Expectations() {
525             {
526                 collaborator.addElements(this.<List<String>> withNotNull());
527                 result = new Delegate<Object>() {
528                     void delegate(Collection<String> elements) {
529                         elements.add("test");
530                     }
531                 };
532             }
533         };
534 
535         List<String> elements = new ArrayList<>();
536         new Collaborator().addElements(elements);
537 
538         assertTrue(elements.contains("test"));
539     }
540 
541     /**
542      * Delegate receiving null arguments.
543      *
544      * @param collaborator
545      *            the collaborator
546      */
547     @Test
548     public void delegateReceivingNullArguments(@Mocked final Collaborator collaborator) {
549         new Expectations() {
550             {
551                 collaborator.doSomething(true, null, null);
552                 result = new Delegate<Object>() {
553                     String delegate(boolean b, int[] i, String s) {
554                         // noinspection ImplicitArrayToString
555                         return b + " " + i + " " + s;
556                     }
557                 };
558             }
559         };
560 
561         String s = new Collaborator().doSomething(true, null, null);
562         assertEquals("true null null", s);
563     }
564 
565     /**
566      * Delegate with two methods.
567      *
568      * @param collaborator
569      *            the collaborator
570      */
571     @Test
572     public void delegateWithTwoMethods(@Mocked final Collaborator collaborator) {
573         new Expectations() {
574             {
575                 collaborator.doSomething(true, null, "str");
576                 result = new Delegate<Object>() {
577                     private String someOther() {
578                         return "";
579                     }
580 
581                     void doSomething(boolean b, int[] i, String s) {
582                     }
583                 };
584             }
585         };
586 
587         assertNull(collaborator.doSomething(true, null, "str"));
588     }
589 
590     /**
591      * Delegate with single method having A different name.
592      *
593      * @param collaborator
594      *            the collaborator
595      */
596     @Test
597     public void delegateWithSingleMethodHavingADifferentName(@Mocked final Collaborator collaborator) {
598         new Expectations() {
599             {
600                 collaborator.doSomething(true, null, "str");
601                 result = new Delegate<Object>() {
602                     void onReplay(boolean b, int[] i, String s) {
603                         assertTrue(b);
604                         assertNull(i);
605                         assertEquals("str", s);
606                     }
607                 };
608             }
609         };
610 
611         assertNull(new Collaborator().doSomething(true, null, "str"));
612     }
613 
614     /**
615      * Delegate with single method having no parameters.
616      *
617      * @param collaborator
618      *            the collaborator
619      */
620     @Test
621     public void delegateWithSingleMethodHavingNoParameters(@Mocked final Collaborator collaborator) {
622         new Expectations() {
623             {
624                 collaborator.doSomething(anyBoolean, null, null);
625                 result = new Delegate<Object>() {
626                     String onReplay() {
627                         return "action";
628                     }
629                 };
630             }
631         };
632 
633         String result = new Collaborator().doSomething(true, null, null);
634 
635         assertEquals("action", result);
636     }
637 
638     /**
639      * Delegate with single method having no parameters except for invocation context.
640      *
641      * @param collaborator
642      *            the collaborator
643      */
644     @Test
645     public void delegateWithSingleMethodHavingNoParametersExceptForInvocationContext(
646             @Mocked final Collaborator collaborator) {
647         new Expectations() {
648             {
649                 collaborator.doSomething(anyBoolean, null, null);
650                 result = new Delegate<Object>() {
651                     void doSomething(Invocation inv) {
652                         assertEquals(1, inv.getInvocationCount());
653                     }
654                 };
655             }
656         };
657 
658         assertNull(new Collaborator().doSomething(false, new int[] { 1, 2 }, "test"));
659     }
660 
661     /**
662      * Delegate with one method having different parameters.
663      *
664      * @param collaborator
665      *            the collaborator
666      */
667     @Test
668     public void delegateWithOneMethodHavingDifferentParameters(@Mocked final Collaborator collaborator) {
669         new Expectations() {
670             {
671                 collaborator.doSomething(true, null, "str");
672                 result = new Delegate<Object>() {
673                     void delegate(boolean b, String s) {
674                     }
675                 };
676             }
677         };
678 
679         Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
680             collaborator.doSomething(true, null, "str");
681         });
682         assertEquals("Failure to invoke method: void mockit.DelegateTest$18$1.delegate(boolean,java.lang.String)",
683                 throwable.getMessage());
684     }
685 
686     /**
687      * Delegate with two non private methods.
688      *
689      * @param collaborator
690      *            the collaborator
691      */
692     @Test
693     public void delegateWithTwoNonPrivateMethods(@Mocked final Collaborator collaborator) {
694         thrown.expect(IllegalArgumentException.class);
695         thrown.expectMessage("More than one candidate delegate method found: ");
696         thrown.expectMessage("someOther()");
697         thrown.expectMessage("doSomethingElse(boolean,int[],String)");
698 
699         new Expectations() {
700             {
701                 collaborator.doSomething(true, null, "str");
702                 result = new Delegate<Object>() {
703                     String someOther() {
704                         return "";
705                     }
706 
707                     void doSomethingElse(boolean b, int[] i, String s) {
708                     }
709                 };
710             }
711         };
712     }
713 
714     /**
715      * Delegate causing concurrent mock invocation.
716      *
717      * @param mock
718      *            the mock
719      */
720     @Test
721     public void delegateCausingConcurrentMockInvocation(@Mocked final Collaborator mock) {
722         final Collaborator collaborator = new Collaborator();
723         final Thread t = new Thread(new Runnable() {
724             @Override
725             public void run() {
726                 collaborator.doSomething(false, null, "");
727             }
728         });
729 
730         new Expectations() {
731             {
732                 mock.getValue();
733                 times = 1;
734                 result = new Delegate<Object>() {
735                     int executeInAnotherThread() throws Exception {
736                         t.start();
737                         t.join();
738                         return 1;
739                     }
740                 };
741             }
742         };
743 
744         assertEquals(1, collaborator.getValue());
745     }
746 
747     /**
748      * Delegate which calls the same mocked method.
749      *
750      * @param mock
751      *            the mock
752      */
753     @Test
754     public void delegateWhichCallsTheSameMockedMethod(@Mocked final Collaborator mock) {
755         new Expectations() {
756             {
757                 mock.getValue();
758                 result = new Delegate<Object>() {
759                     int count;
760 
761                     // Would result in a StackOverflowError without a termination condition.
762                     int delegate() {
763                         return count++ > 1 ? 123 : 1 + mock.getValue();
764                     }
765                 };
766             }
767         };
768 
769         assertEquals(125, mock.getValue());
770     }
771 
772     /**
773      * Delegate which calls another mocked method.
774      *
775      * @param mock
776      *            the mock
777      */
778     @Test
779     public void delegateWhichCallsAnotherMockedMethod(@Mocked final Collaborator mock) {
780         new Expectations() {
781             {
782                 mock.getValue();
783                 result = new Delegate<Object>() {
784                     int delegate() {
785                         return mock.finalMethod();
786                     }
787                 };
788 
789                 mock.finalMethod();
790                 result = 'A';
791             }
792         };
793 
794         assertEquals('A', mock.getValue());
795     }
796 
797     /**
798      * Delegate which calls another mocked method partial mocking of instance.
799      */
800     @Test
801     public void delegateWhichCallsAnotherMockedMethod_partialMockingOfInstance() {
802         final Collaborator collaborator = new Collaborator();
803 
804         new Expectations(collaborator) {
805             {
806                 collaborator.getValue();
807                 result = new Delegate<Object>() {
808                     int delegate() {
809                         return collaborator.finalMethod();
810                     }
811                 };
812 
813                 collaborator.finalMethod();
814                 result = 'A';
815             }
816         };
817 
818         assertEquals('A', collaborator.getValue());
819     }
820 
821     /**
822      * Delegate which calls another mocked method injectable mocking.
823      *
824      * @param mock
825      *            the mock
826      */
827     @Test
828     public void delegateWhichCallsAnotherMockedMethod_injectableMocking(@Injectable final Collaborator mock) {
829         new Expectations() {
830             {
831                 mock.getValue();
832                 result = new Delegate<Object>() {
833                     int delegate() {
834                         return mock.finalMethod();
835                     }
836                 };
837 
838                 mock.finalMethod();
839                 result = 'A';
840             }
841         };
842 
843         assertEquals('A', mock.getValue());
844     }
845 
846     /**
847      * Delegate which calls another mocked method producing A cascaded instance.
848      *
849      * @param mock
850      *            the mock
851      */
852     @Test
853     public void delegateWhichCallsAnotherMockedMethodProducingACascadedInstance(@Mocked final Collaborator mock) {
854         new Expectations() {
855             {
856                 mock.getFoo().doSomething();
857                 result = 123;
858 
859                 mock.getValue();
860                 result = new Delegate<Object>() {
861                     int delegate() {
862                         return mock.getFoo().doSomething();
863                     }
864                 };
865             }
866         };
867 
868         assertEquals(123, mock.getFoo().doSomething());
869         assertEquals(123, mock.getValue());
870     }
871 
872     /**
873      * Delegate calling mocked method later verified.
874      *
875      * @param collaborator
876      *            the collaborator
877      * @param action
878      *            the action
879      */
880     @Test
881     public void delegateCallingMockedMethodLaterVerified(@Mocked final Collaborator collaborator,
882             @Mocked final Runnable action) {
883         new Expectations() {
884             {
885                 collaborator.getFoo();
886                 result = new Delegate<Object>() {
887                     void delegate() {
888                         action.run();
889                     }
890                 };
891             }
892         };
893 
894         collaborator.getFoo();
895 
896         new Verifications() {
897             {
898                 action.run();
899             }
900         };
901     }
902 
903     /**
904      * Convert value returned from delegate when returns types differ.
905      *
906      * @param mock
907      *            the mock
908      */
909     @Test
910     public void convertValueReturnedFromDelegateWhenReturnsTypesDiffer(@Mocked final Collaborator mock) {
911         new Expectations() {
912             {
913                 mock.getValue();
914                 result = new Delegate<Object>() {
915                     byte delegate() {
916                         return (byte) 123;
917                     }
918                 };
919             }
920         };
921 
922         int value = mock.getValue();
923 
924         assertEquals(123, value);
925     }
926 
927     /**
928      * Return inconvertible value from delegate when returns types differ.
929      *
930      * @param mock
931      *            the mock
932      */
933     @Test
934     public void returnInconvertibleValueFromDelegateWhenReturnsTypesDiffer(@Mocked final Collaborator mock) {
935         new Expectations() {
936             {
937                 mock.getValue();
938                 result = new Delegate<Object>() {
939                     String delegate() {
940                         return "abc";
941                     }
942                 };
943             }
944         };
945 
946         Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
947             mock.getValue();
948         });
949         assertEquals(
950                 "Value of type String incompatible with return type int of mockit.DelegateTest$Collaborator#getValue()",
951                 throwable.getMessage());
952     }
953 
954     /**
955      * Return void from delegate method for recorded method having primitive return type.
956      *
957      * @param mock
958      *            the mock
959      */
960     @Test
961     public void returnVoidFromDelegateMethodForRecordedMethodHavingPrimitiveReturnType(
962             @Mocked final Collaborator mock) {
963         new Expectations() {
964             {
965                 mock.getValue();
966                 result = new Delegate<Object>() {
967                     void delegate() {
968                     }
969                 };
970             }
971         };
972 
973         Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
974             mock.getValue();
975         });
976         assertEquals(
977                 "void return type incompatible with return type int of mockit.DelegateTest$Collaborator#getValue()",
978                 throwable.getMessage());
979     }
980 
981     /**
982      * Return byte array from delegate method.
983      *
984      * @param mock
985      *            the mock
986      */
987     @Test
988     public void returnByteArrayFromDelegateMethod(@Mocked final Collaborator mock) {
989         final byte[] bytes = "test".getBytes();
990         new Expectations() {
991             {
992                 mock.getArray();
993                 result = new Delegate<Object>() {
994                     byte[] delegate() {
995                         return bytes;
996                     }
997                 };
998             }
999         };
1000 
1001         assertSame(bytes, mock.getArray());
1002     }
1003 
1004     /**
1005      * Return value of correct type from delegate method returning A supertype.
1006      *
1007      * @param mock
1008      *            the mock
1009      */
1010     @Test
1011     public void returnValueOfCorrectTypeFromDelegateMethodReturningASupertype(@Mocked final Collaborator mock) {
1012         final Foo expected = new Foo();
1013 
1014         new Expectations() {
1015             {
1016                 mock.getFoo();
1017                 result = new Delegate<Object>() {
1018                     Object delegate() {
1019                         return expected;
1020                     }
1021                 };
1022             }
1023         };
1024 
1025         Foo actual = mock.getFoo();
1026 
1027         assertSame(expected, actual);
1028     }
1029 }