View Javadoc
1   package mockit;
2   
3   import static org.junit.jupiter.api.Assertions.assertEquals;
4   import static org.junit.jupiter.api.Assertions.assertFalse;
5   import static org.junit.jupiter.api.Assertions.assertNotNull;
6   import static org.junit.jupiter.api.Assertions.assertNotSame;
7   import static org.junit.jupiter.api.Assertions.assertNull;
8   import static org.junit.jupiter.api.Assertions.assertSame;
9   import static org.junit.jupiter.api.Assertions.assertThrows;
10  import static org.junit.jupiter.api.Assertions.assertTrue;
11  import static org.junit.jupiter.api.Assertions.fail;
12  
13  import java.io.ByteArrayOutputStream;
14  import java.io.File;
15  import java.io.IOException;
16  import java.io.OutputStream;
17  import java.lang.management.CompilationMXBean;
18  import java.lang.management.ManagementFactory;
19  import java.net.InetAddress;
20  import java.net.InetSocketAddress;
21  import java.net.Socket;
22  import java.net.SocketAddress;
23  import java.nio.channels.SocketChannel;
24  import java.nio.file.Path;
25  import java.util.Arrays;
26  import java.util.Date;
27  import java.util.HashMap;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.concurrent.Future;
31  
32  import mockit.internal.expectations.invocation.MissingInvocation;
33  
34  import org.junit.jupiter.api.Disabled;
35  import org.junit.jupiter.api.MethodOrderer.MethodName;
36  import org.junit.jupiter.api.Test;
37  import org.junit.jupiter.api.TestMethodOrder;
38  
39  /**
40   * The Class CascadingParametersTest.
41   */
42  @SuppressWarnings("ConstantConditions")
43  @TestMethodOrder(MethodName.class)
44  final class CascadingParametersTest {
45  
46      /**
47       * The Class Foo.
48       */
49      static class Foo {
50  
51          /**
52           * Gets the bar.
53           *
54           * @return the bar
55           */
56          Bar getBar() {
57              return null;
58          }
59  
60          /**
61           * Global bar.
62           *
63           * @return the bar
64           */
65          static Bar globalBar() {
66              return null;
67          }
68  
69          /**
70           * Do something.
71           *
72           * @param s
73           *            the s
74           */
75          void doSomething(String s) {
76              throw new RuntimeException(s);
77          }
78  
79          /**
80           * Gets the int value.
81           *
82           * @return the int value
83           */
84          int getIntValue() {
85              return 1;
86          }
87  
88          /**
89           * Gets the boolean value.
90           *
91           * @return the boolean value
92           */
93          Boolean getBooleanValue() {
94              return true;
95          }
96  
97          /**
98           * Gets the list.
99           *
100          * @return the list
101          */
102         final List<Integer> getList() {
103             return null;
104         }
105 
106         /**
107          * Gets the map.
108          *
109          * @return the map
110          */
111         HashMap<?, ?> getMap() {
112             return null;
113         }
114     }
115 
116     /**
117      * The Class Bar.
118      */
119     static class Bar {
120 
121         /**
122          * Instantiates a new bar.
123          */
124         Bar() {
125             throw new RuntimeException();
126         }
127 
128         /**
129          * Do something.
130          *
131          * @return the int
132          */
133         int doSomething() {
134             return 1;
135         }
136 
137         /**
138          * Gets the baz.
139          *
140          * @return the baz
141          */
142         Baz getBaz() {
143             return null;
144         }
145 
146         /**
147          * Gets the baz.
148          *
149          * @param i
150          *            the i
151          *
152          * @return the baz
153          */
154         Baz getBaz(@SuppressWarnings("unused") int i) {
155             return null;
156         }
157 
158         /**
159          * Gets the enum.
160          *
161          * @return the enum
162          */
163         AnEnum getEnum() {
164             return null;
165         }
166 
167         /**
168          * Static method.
169          *
170          * @return the string
171          */
172         static String staticMethod() {
173             return "notMocked";
174         }
175     }
176 
177     /**
178      * The Class SubBar.
179      */
180     static final class SubBar extends Bar {
181     }
182 
183     /**
184      * The Interface Baz.
185      */
186     public interface Baz {
187 
188         /**
189          * Run it.
190          */
191         void runIt();
192 
193         /**
194          * Gets the date.
195          *
196          * @return the date
197          */
198         Date getDate();
199     }
200 
201     /**
202      * The Enum AnEnum.
203      */
204     enum AnEnum {
205         /** The First. */
206         First,
207         /** The Second. */
208         Second,
209         /** The Third. */
210         Third
211     }
212 
213     /** The cascaded bar 1. */
214     static Bar cascadedBar1;
215 
216     /** The cascaded bar 2. */
217     static Bar cascadedBar2;
218 
219     /**
220      * Cascade one level during replay.
221      *
222      * @param foo
223      *            the foo
224      */
225     @Test
226     void cascadeOneLevelDuringReplay(@Mocked Foo foo) {
227         cascadedBar1 = foo.getBar();
228         assertEquals(0, cascadedBar1.doSomething());
229 
230         cascadedBar2 = Foo.globalBar();
231         assertEquals(0, cascadedBar2.doSomething());
232 
233         Bar bar = foo.getBar();
234         assertSame(cascadedBar1, bar);
235 
236         Bar globalBar = Foo.globalBar();
237         assertSame(cascadedBar2, globalBar);
238         assertNotSame(bar, globalBar);
239 
240         foo.doSomething("test");
241         assertEquals(0, foo.getIntValue());
242         assertFalse(foo.getBooleanValue());
243         assertTrue(foo.getList().isEmpty());
244 
245         Map<?, ?> map = foo.getMap();
246         assertNull(map);
247     }
248 
249     /**
250      * Verify that previous cascaded instances have been discarded.
251      *
252      * @param foo
253      *            the foo
254      */
255     @Test
256     void verifyThatPreviousCascadedInstancesHaveBeenDiscarded(@Mocked Foo foo) {
257         Bar bar = foo.getBar();
258         assertNotSame(cascadedBar1, bar);
259 
260         Bar globalBar = Foo.globalBar();
261         assertNotSame(cascadedBar2, globalBar);
262     }
263 
264     /**
265      * Verify that static methods and constructors are not mocked when cascading.
266      *
267      * @param foo
268      *            the foo
269      */
270     @Test
271     void verifyThatStaticMethodsAndConstructorsAreNotMockedWhenCascading(@Mocked Foo foo) {
272         foo.getBar();
273 
274         assertEquals("notMocked", Bar.staticMethod());
275 
276         try {
277             new Bar();
278             fail();
279         } catch (RuntimeException ignored) {
280         }
281     }
282 
283     /**
284      * Verify that static methods and constructors are mocked when cascaded mock is mocked normally.
285      *
286      * @param mockFoo
287      *            the mock foo
288      * @param mockBar
289      *            the mock bar
290      */
291     @Test
292     void verifyThatStaticMethodsAndConstructorsAreMockedWhenCascadedMockIsMockedNormally(@Mocked Foo mockFoo,
293             @Mocked Bar mockBar) {
294         assertSame(mockBar, mockFoo.getBar());
295         assertEquals(0, mockBar.doSomething());
296         assertNull(Bar.staticMethod());
297         new Bar();
298     }
299 
300     /**
301      * Use available mocked instance of subclass as cascaded instance.
302      *
303      * @param foo
304      *            the foo
305      * @param bar
306      *            the bar
307      */
308     @Test
309     void useAvailableMockedInstanceOfSubclassAsCascadedInstance(@Mocked Foo foo, @Mocked SubBar bar) {
310         Bar cascadedBar = foo.getBar();
311 
312         assertSame(bar, cascadedBar);
313     }
314 
315     /**
316      * Replace cascaded instance with first one of two injectable instances.
317      *
318      * @param foo
319      *            the foo
320      * @param bar1
321      *            the bar 1
322      * @param bar2
323      *            the bar 2
324      */
325     @Test
326     void replaceCascadedInstanceWithFirstOneOfTwoInjectableInstances(@Mocked final Foo foo, @Injectable final Bar bar1,
327             @Injectable Bar bar2) {
328         new Expectations() {
329             {
330                 foo.getBar();
331                 result = bar1;
332             }
333         };
334 
335         Bar cascadedBar = foo.getBar();
336 
337         assertSame(bar1, cascadedBar);
338         assertEquals(0, bar1.doSomething());
339         assertEquals(0, bar2.doSomething());
340     }
341 
342     /**
343      * Cascade one level during record.
344      *
345      * @param mockFoo
346      *            the mock foo
347      */
348     @Test
349     void cascadeOneLevelDuringRecord(@Mocked final Foo mockFoo) {
350         final List<Integer> list = Arrays.asList(1, 2, 3);
351 
352         new Expectations() {
353             {
354                 mockFoo.doSomething(anyString);
355                 minTimes = 2;
356                 mockFoo.getBar().doSomething();
357                 result = 2;
358                 Foo.globalBar().doSomething();
359                 result = 3;
360                 mockFoo.getBooleanValue();
361                 result = true;
362                 mockFoo.getIntValue();
363                 result = -1;
364                 mockFoo.getList();
365                 result = list;
366             }
367         };
368 
369         Foo foo = new Foo();
370         foo.doSomething("1");
371         assertEquals(2, foo.getBar().doSomething());
372         foo.doSomething("2");
373         assertEquals(3, Foo.globalBar().doSomething());
374         assertTrue(foo.getBooleanValue());
375         assertEquals(-1, foo.getIntValue());
376         assertSame(list, foo.getList());
377     }
378 
379     /**
380      * Cascade one level during verify.
381      *
382      * @param foo
383      *            the foo
384      */
385     @Test
386     void cascadeOneLevelDuringVerify(@Mocked final Foo foo) {
387         Bar bar = foo.getBar();
388         bar.doSomething();
389         bar.doSomething();
390 
391         Foo.globalBar().doSomething();
392 
393         assertEquals(0, foo.getIntValue());
394         assertFalse(foo.getBooleanValue());
395 
396         assertTrue(foo.getList().isEmpty());
397 
398         new Verifications() {
399             {
400                 foo.getBar().doSomething();
401                 minTimes = 2;
402                 Foo.globalBar().doSomething();
403                 times = 1;
404             }
405         };
406 
407         new VerificationsInOrder() {
408             {
409                 foo.getIntValue();
410                 foo.getBooleanValue();
411             }
412         };
413     }
414 
415     /**
416      * Cascade two levels during replay.
417      *
418      * @param foo
419      *            the foo
420      */
421     @Test
422     void cascadeTwoLevelsDuringReplay(@Mocked Foo foo) {
423         foo.getBar().getBaz().runIt();
424     }
425 
426     /**
427      * Cascade two levels during record.
428      *
429      * @param mockFoo
430      *            the mock foo
431      */
432     @Test
433     void cascadeTwoLevelsDuringRecord(@Mocked final Foo mockFoo) {
434         new Expectations() {
435             {
436                 mockFoo.getBar().doSomething();
437                 result = 1;
438                 Foo.globalBar().doSomething();
439                 result = 2;
440 
441                 mockFoo.getBar().getBaz().runIt();
442                 times = 2;
443             }
444         };
445 
446         Foo foo = new Foo();
447         assertEquals(1, foo.getBar().doSomething());
448         assertEquals(2, Foo.globalBar().doSomething());
449 
450         Baz baz = foo.getBar().getBaz();
451         baz.runIt();
452         baz.runIt();
453     }
454 
455     /**
456      * Cascade one level and verify invocation on last mock only.
457      *
458      * @param foo
459      *            the foo
460      * @param bar
461      *            the bar
462      */
463     @Test
464     void cascadeOneLevelAndVerifyInvocationOnLastMockOnly(@Mocked Foo foo, @Injectable final Bar bar) {
465         Bar fooBar = foo.getBar();
466         assertSame(bar, fooBar);
467         fooBar.doSomething();
468 
469         new Verifications() {
470             {
471                 bar.doSomething();
472             }
473         };
474     }
475 
476     /**
477      * Cascade two levels with invocation recorded on last mock only.
478      *
479      * @param foo
480      *            the foo
481      * @param baz
482      *            the baz
483      */
484     @Test
485     void cascadeTwoLevelsWithInvocationRecordedOnLastMockOnly(@Mocked Foo foo, @Mocked final Baz baz) {
486         new Expectations() {
487             {
488                 baz.runIt();
489                 times = 1;
490             }
491         };
492 
493         Baz cascadedBaz = foo.getBar().getBaz();
494         cascadedBaz.runIt();
495     }
496 
497     /**
498      * Cascade two levels and verify invocation on last mock only.
499      *
500      * @param foo
501      *            the foo
502      * @param baz
503      *            the baz
504      */
505     @Test
506     void cascadeTwoLevelsAndVerifyInvocationOnLastMockOnly(@Mocked Foo foo, @Mocked final Baz baz) {
507         Baz cascadedBaz = foo.getBar().getBaz();
508         assertSame(baz, cascadedBaz);
509         cascadedBaz.runIt();
510 
511         new Verifications() {
512             {
513                 baz.runIt();
514             }
515         };
516     }
517 
518     // Tests using the java.lang.Process and java.lang.ProcessBuilder classes //////////////////////////////////////////
519 
520     /**
521      * Cascade on JRE classes.
522      *
523      * @param pb
524      *            the pb
525      *
526      * @throws Exception
527      *             the exception
528      */
529     @Test
530     void cascadeOnJREClasses(@Mocked final ProcessBuilder pb) throws Exception {
531         new Expectations() {
532             {
533                 ProcessBuilder sameBuilder = pb.directory((File) any);
534                 assertSame(sameBuilder, pb);
535 
536                 Process process = sameBuilder.start();
537                 process.getOutputStream().write(5);
538                 process.exitValue();
539                 result = 1;
540             }
541         };
542 
543         Process process = new ProcessBuilder("test").directory(Path.of("myDir").toFile()).start();
544         process.getOutputStream().write(5);
545         process.getOutputStream().flush();
546         assertEquals(1, process.exitValue());
547     }
548 
549     /**
550      * Return same mocked instance through cascading even with multiple candidates available.
551      *
552      * @param pb1
553      *            the pb 1
554      * @param pb2
555      *            the pb 2
556      */
557     @Test
558     void returnSameMockedInstanceThroughCascadingEvenWithMultipleCandidatesAvailable(@Injectable ProcessBuilder pb1,
559             @Injectable ProcessBuilder pb2) {
560         assertSame(pb1, pb1.command("a"));
561         assertSame(pb2, pb2.command("b"));
562     }
563 
564     /**
565      * Creates the OS process to copy temp files.
566      *
567      * @param pb
568      *            the pb
569      *
570      * @throws Exception
571      *             the exception
572      */
573     @Test
574     void createOSProcessToCopyTempFiles(@Mocked final ProcessBuilder pb) throws Exception {
575         // Code under test creates a new process to execute an OS-specific command.
576         String cmdLine = "copy /Y *.txt D:\\TEMP";
577         File wrkDir = Path.of("C:\\TEMP").toFile();
578         Process copy = new ProcessBuilder().command(cmdLine).directory(wrkDir).start();
579         int exit = copy.waitFor();
580 
581         if (exit != 0) {
582             throw new RuntimeException("Process execution failed");
583         }
584 
585         // Verify the desired process was created with the correct command.
586         new Verifications() {
587             {
588                 pb.command(withSubstring("copy")).start();
589             }
590         };
591     }
592 
593     // Tests using java.net classes ////////////////////////////////////////////////////////////////////////////////////
594 
595     /**
596      * Record and verify expectations on cascaded mocks.
597      *
598      * @param anySocket
599      *            the any socket
600      * @param cascadedChannel
601      *            the cascaded channel
602      * @param inetAddr
603      *            the inet addr
604      *
605      * @throws Exception
606      *             the exception
607      */
608     // TODO JWL 2/18/2024 Test not allowed on jdk21
609     @Disabled
610     @Test
611     void recordAndVerifyExpectationsOnCascadedMocks(@Mocked Socket anySocket,
612             @Mocked final SocketChannel cascadedChannel, @Mocked InetSocketAddress inetAddr) throws Exception {
613         Socket sk = new Socket();
614         SocketChannel ch = sk.getChannel();
615 
616         if (!ch.isConnected()) {
617             SocketAddress sa = new InetSocketAddress("remoteHost", 123);
618             ch.connect(sa);
619         }
620 
621         InetAddress adr1 = sk.getInetAddress();
622         InetAddress adr2 = sk.getLocalAddress();
623         assertNotSame(adr1, adr2);
624         sk.close();
625 
626         new Verifications() {
627             {
628                 cascadedChannel.connect((SocketAddress) withNotNull());
629             }
630         };
631     }
632 
633     /**
634      * A factory for creating Socket objects.
635      */
636     static final class SocketFactory {
637 
638         /**
639          * Creates a new Socket object.
640          *
641          * @return the socket
642          */
643         public Socket createSocket() {
644             return new Socket();
645         }
646 
647         /**
648          * Creates a new Socket object.
649          *
650          * @param host
651          *            the host
652          * @param port
653          *            the port
654          *
655          * @return the socket
656          *
657          * @throws IOException
658          *             Signals that an I/O exception has occurred.
659          */
660         public Socket createSocket(String host, int port) throws IOException {
661             return new Socket(host, port);
662         }
663     }
664 
665     /**
666      * Cascade one level with argument matchers.
667      *
668      * @param sf
669      *            the sf
670      *
671      * @throws Exception
672      *             the exception
673      */
674     @Test
675     void cascadeOneLevelWithArgumentMatchers(@Mocked final SocketFactory sf) throws Exception {
676         new Expectations() {
677             {
678                 sf.createSocket(anyString, 80);
679                 result = null;
680             }
681         };
682 
683         assertNull(sf.createSocket("expected", 80));
684         assertNotNull(sf.createSocket("unexpected", 8080));
685     }
686 
687     /**
688      * Record and verify one level deep.
689      *
690      * @param sf
691      *            the sf
692      *
693      * @throws Exception
694      *             the exception
695      */
696     @Test
697     void recordAndVerifyOneLevelDeep(@Mocked final SocketFactory sf) throws Exception {
698         final OutputStream out = new ByteArrayOutputStream();
699 
700         new Expectations() {
701             {
702                 sf.createSocket().getOutputStream();
703                 result = out;
704             }
705         };
706 
707         assertSame(out, sf.createSocket().getOutputStream());
708     }
709 
710     /**
711      * Record and verify on two cascading mocks of the same type.
712      *
713      * @param sf1
714      *            the sf 1
715      * @param sf2
716      *            the sf 2
717      *
718      * @throws Exception
719      *             the exception
720      */
721     @Test
722     void recordAndVerifyOnTwoCascadingMocksOfTheSameType(@Mocked final SocketFactory sf1,
723             @Mocked final SocketFactory sf2) throws Exception {
724         final OutputStream out1 = new ByteArrayOutputStream();
725         final OutputStream out2 = new ByteArrayOutputStream();
726 
727         new Expectations() {
728             {
729                 sf1.createSocket().getOutputStream();
730                 result = out1;
731                 sf2.createSocket().getOutputStream();
732                 result = out2;
733             }
734         };
735 
736         assertSame(out1, sf1.createSocket().getOutputStream());
737         assertSame(out2, sf2.createSocket().getOutputStream());
738 
739         new VerificationsInOrder() {
740             {
741                 sf1.createSocket().getOutputStream();
742                 sf2.createSocket().getOutputStream();
743             }
744         };
745     }
746 
747     /**
748      * Record and verify same invocation on mocks returned from invocations with different arguments.
749      *
750      * @param sf
751      *            the sf
752      *
753      * @throws Exception
754      *             the exception
755      */
756     @Test
757     void recordAndVerifySameInvocationOnMocksReturnedFromInvocationsWithDifferentArguments(
758             @Mocked final SocketFactory sf) throws Exception {
759         new Expectations() {
760             {
761                 sf.createSocket().getPort();
762                 result = 1;
763                 sf.createSocket("first", 80).getPort();
764                 result = 2;
765                 sf.createSocket("second", 80).getPort();
766                 result = 3;
767                 sf.createSocket(anyString, 81).getPort();
768                 result = 4;
769             }
770         };
771 
772         assertEquals(1, sf.createSocket().getPort());
773         assertEquals(2, sf.createSocket("first", 80).getPort());
774         assertEquals(3, sf.createSocket("second", 80).getPort());
775         assertEquals(4, sf.createSocket("third", 81).getPort());
776 
777         new VerificationsInOrder() {
778             {
779                 sf.createSocket().getPort();
780                 times = 1;
781                 sf.createSocket("first", 80).getPort();
782                 sf.createSocket("second", 80).getPort();
783                 sf.createSocket(anyString, 81).getPort();
784                 maxTimes = 1;
785                 sf.createSocket("fourth", -1);
786                 times = 0;
787             }
788         };
789     }
790 
791     /**
792      * Cascade on inherited method.
793      *
794      * @param sc
795      *            the sc
796      */
797     @Test
798     void cascadeOnInheritedMethod(@Mocked SocketChannel sc) {
799         assertNotNull(sc.provider());
800     }
801 
802     /**
803      * Record and verify with mixed cascade levels.
804      *
805      * @param sf
806      *            the sf
807      *
808      * @throws Exception
809      *             the exception
810      */
811     @Test
812     void recordAndVerifyWithMixedCascadeLevels(@Mocked final SocketFactory sf) throws Exception {
813         new Expectations() {
814             {
815                 sf.createSocket("first", 80).getKeepAlive();
816                 result = true;
817                 sf.createSocket("second", anyInt).getChannel().close();
818                 times = 1;
819             }
820         };
821 
822         sf.createSocket("second", 80).getChannel().close();
823         assertTrue(sf.createSocket("first", 80).getKeepAlive());
824         sf.createSocket("first", 8080).getChannel().provider().openPipe();
825 
826         new Verifications() {
827             {
828                 sf.createSocket("first", 8080).getChannel().provider().openPipe();
829             }
830         };
831     }
832 
833     // Cascading other Java SE types ///////////////////////////////////////////////////////////////////////////////////
834 
835     /**
836      * The Class SomeClass.
837      */
838     static class SomeClass {
839         /**
840          * Do something.
841          *
842          * @return the future
843          */
844         Future<Foo> doSomething() {
845             return null;
846         }
847     }
848 
849     /**
850      * Cascade A future.
851      *
852      * @param mock
853      *            the mock
854      *
855      * @throws Exception
856      *             the exception
857      */
858     @Test
859     void cascadeAFuture(@Mocked SomeClass mock) throws Exception {
860         Future<Foo> f = mock.doSomething();
861         Foo foo = f.get();
862 
863         assertNotNull(foo);
864     }
865 
866     // Other tests /////////////////////////////////////////////////////////////////////////////////////////////////////
867 
868     /**
869      * Record expectation on cascaded mock.
870      *
871      * @param foo
872      *            the foo
873      * @param mockBar
874      *            the mock bar
875      */
876     @Test
877     void recordExpectationOnCascadedMock(@Mocked Foo foo, @Mocked final Bar mockBar) {
878         new Expectations() {
879             {
880                 mockBar.doSomething();
881                 times = 1;
882                 result = 123;
883             }
884         };
885 
886         Bar bar = foo.getBar();
887         assertEquals(123, bar.doSomething());
888     }
889 
890     /**
891      * Override two cascaded mocks of the same type.
892      *
893      * @param foo1
894      *            the foo 1
895      * @param foo2
896      *            the foo 2
897      * @param mockBar1
898      *            the mock bar 1
899      * @param mockBar2
900      *            the mock bar 2
901      */
902     @Test
903     void overrideTwoCascadedMocksOfTheSameType(@Mocked final Foo foo1, @Mocked final Foo foo2,
904             @Mocked final Bar mockBar1, @Mocked final Bar mockBar2) {
905         new Expectations() {
906             {
907                 foo1.getBar();
908                 result = mockBar1;
909                 foo2.getBar();
910                 result = mockBar2;
911                 mockBar1.doSomething();
912                 mockBar2.doSomething();
913             }
914         };
915 
916         Bar bar1 = foo1.getBar();
917         Bar bar2 = foo2.getBar();
918         bar1.doSomething();
919         bar2.doSomething();
920     }
921 
922     /**
923      * Override two cascaded mocks of the same type but replay in different order.
924      *
925      * @param foo1
926      *            the foo 1
927      * @param foo2
928      *            the foo 2
929      * @param mockBar1
930      *            the mock bar 1
931      * @param mockBar2
932      *            the mock bar 2
933      */
934     @Test
935     void overrideTwoCascadedMocksOfTheSameTypeButReplayInDifferentOrder(@Mocked final Foo foo1, @Mocked final Foo foo2,
936             @Injectable final Bar mockBar1, @Mocked final Bar mockBar2) {
937         assertThrows(MissingInvocation.class, () -> {
938             new Expectations() {
939                 {
940                     foo1.getBar();
941                     result = mockBar1;
942                     foo2.getBar();
943                     result = mockBar2;
944                 }
945             };
946 
947             Bar bar1 = foo1.getBar();
948             Bar bar2 = foo2.getBar();
949             bar2.doSomething();
950             bar1.doSomething();
951 
952             new VerificationsInOrder() {
953                 {
954                     mockBar1.doSomething();
955                     mockBar2.doSomething();
956                 }
957             };
958         });
959     }
960 
961     /**
962      * Cascaded enum.
963      *
964      * @param mock
965      *            the mock
966      */
967     @Test
968     void cascadedEnum(@Mocked final Foo mock) {
969         new Expectations() {
970             {
971                 mock.getBar().getEnum();
972                 result = AnEnum.Second;
973             }
974         };
975 
976         assertEquals(AnEnum.Second, mock.getBar().getEnum());
977     }
978 
979     /**
980      * Cascaded enum returning consecutive values through result field.
981      *
982      * @param mock
983      *            the mock
984      */
985     @Test
986     void cascadedEnumReturningConsecutiveValuesThroughResultField(@Mocked final Foo mock) {
987         new Expectations() {
988             {
989                 mock.getBar().getEnum();
990                 result = AnEnum.First;
991                 result = AnEnum.Second;
992                 result = AnEnum.Third;
993             }
994         };
995 
996         assertSame(AnEnum.First, mock.getBar().getEnum());
997         assertSame(AnEnum.Second, mock.getBar().getEnum());
998         assertSame(AnEnum.Third, mock.getBar().getEnum());
999     }
1000 
1001     /**
1002      * Cascaded enum returning consecutive values through returns method.
1003      *
1004      * @param mock
1005      *            the mock
1006      */
1007     @Test
1008     void cascadedEnumReturningConsecutiveValuesThroughReturnsMethod(@Mocked final Foo mock) {
1009         new Expectations() {
1010             {
1011                 mock.getBar().getEnum();
1012                 returns(AnEnum.First, AnEnum.Second, AnEnum.Third);
1013             }
1014         };
1015 
1016         assertSame(AnEnum.First, mock.getBar().getEnum());
1017         assertSame(AnEnum.Second, mock.getBar().getEnum());
1018         assertSame(AnEnum.Third, mock.getBar().getEnum());
1019     }
1020 
1021     /**
1022      * Override last cascaded object with non mocked instance.
1023      *
1024      * @param foo
1025      *            the foo
1026      */
1027     @Test
1028     void overrideLastCascadedObjectWithNonMockedInstance(@Mocked final Foo foo) {
1029         final Date newDate = new Date(123);
1030         assertEquals(123, newDate.getTime());
1031 
1032         new Expectations() {
1033             {
1034                 foo.getBar().getBaz().getDate();
1035                 result = newDate;
1036             }
1037         };
1038 
1039         assertSame(newDate, new Foo().getBar().getBaz().getDate());
1040         assertEquals(123, newDate.getTime());
1041     }
1042 
1043     /**
1044      * Return declared mocked instance from multi level cascading.
1045      *
1046      * @param mockedDate
1047      *            the mocked date
1048      * @param foo
1049      *            the foo
1050      */
1051     @Test
1052     void returnDeclaredMockedInstanceFromMultiLevelCascading(@Mocked Date mockedDate, @Mocked Foo foo) {
1053         Date newDate = new Date(123);
1054         assertEquals(0, newDate.getTime());
1055 
1056         Date cascadedDate = new Foo().getBar().getBaz().getDate();
1057 
1058         assertSame(mockedDate, cascadedDate);
1059         assertEquals(0, newDate.getTime());
1060         assertEquals(0, mockedDate.getTime());
1061     }
1062 
1063     /**
1064      * Return injectable mock instance from multi level cascading.
1065      *
1066      * @param mockDate
1067      *            the mock date
1068      * @param foo
1069      *            the foo
1070      */
1071     @Test
1072     void returnInjectableMockInstanceFromMultiLevelCascading(@Injectable Date mockDate, @Mocked Foo foo) {
1073         Date newDate = new Date(123);
1074         assertEquals(123, newDate.getTime());
1075 
1076         Date cascadedDate = new Foo().getBar().getBaz().getDate();
1077 
1078         assertSame(mockDate, cascadedDate);
1079         assertEquals(123, newDate.getTime());
1080         assertEquals(0, mockDate.getTime());
1081     }
1082 
1083     /**
1084      * The Class Factory.
1085      */
1086     static class Factory {
1087         /**
1088          * Creates the.
1089          *
1090          * @return the factory
1091          */
1092         static Factory create() {
1093             return null;
1094         }
1095     }
1096 
1097     /**
1098      * The Class Client.
1099      */
1100     static class Client {
1101         /**
1102          * Gets the other client.
1103          *
1104          * @return the other client
1105          */
1106         OtherClient getOtherClient() {
1107             return null;
1108         }
1109     }
1110 
1111     /**
1112      * The Class OtherClient.
1113      */
1114     static class OtherClient {
1115         /** The Constant F. */
1116         static final Factory F = Factory.create();
1117     }
1118 
1119     /**
1120      * Cascade during static initialization of cascading class.
1121      *
1122      * @param mock1
1123      *            the mock 1
1124      * @param mock2
1125      *            the mock 2
1126      */
1127     @Test
1128     void cascadeDuringStaticInitializationOfCascadingClass(@Mocked Factory mock1, @Mocked Client mock2) {
1129         assertNotNull(mock2.getOtherClient());
1130         assertNotNull(OtherClient.F);
1131     }
1132 
1133     /**
1134      * The Interface LevelZero.
1135      */
1136     public interface LevelZero {
1137         /**
1138          * Gets the foo.
1139          *
1140          * @return the foo
1141          */
1142         Runnable getFoo();
1143     }
1144 
1145     /**
1146      * The Interface LevelOne.
1147      */
1148     public interface LevelOne extends LevelZero {
1149     }
1150 
1151     /**
1152      * The Interface LevelTwo.
1153      */
1154     public interface LevelTwo extends LevelOne {
1155     }
1156 
1157     /**
1158      * Creates the cascaded mock from method defined two levels up an interface hierarchy.
1159      *
1160      * @param mock
1161      *            the mock
1162      */
1163     @Test
1164     void createCascadedMockFromMethodDefinedTwoLevelsUpAnInterfaceHierarchy(@Mocked LevelTwo mock) {
1165         assertNotNull(mock.getFoo());
1166     }
1167 
1168     /**
1169      * The Class AbstractClass.
1170      */
1171     public abstract static class AbstractClass implements LevelZero {
1172     }
1173 
1174     /**
1175      * Cascade type returned from interface implemented by abstract class.
1176      *
1177      * @param mock
1178      *            the mock
1179      */
1180     @Test
1181     void cascadeTypeReturnedFromInterfaceImplementedByAbstractClass(@Mocked AbstractClass mock) {
1182         Runnable foo = mock.getFoo();
1183         assertNotNull(foo);
1184     }
1185 
1186     /**
1187      * Produce different cascaded instances of same interface from different invocations.
1188      *
1189      * @param bar
1190      *            the bar
1191      */
1192     @Test
1193     void produceDifferentCascadedInstancesOfSameInterfaceFromDifferentInvocations(@Mocked Bar bar) {
1194         Baz cascaded1 = bar.getBaz(1);
1195         Baz cascaded2 = bar.getBaz(2);
1196         Baz cascaded3 = bar.getBaz(1);
1197 
1198         assertSame(cascaded1, cascaded3);
1199         assertNotSame(cascaded1, cascaded2);
1200     }
1201 
1202     /**
1203      * Cascade from java management API.
1204      *
1205      * @param mngmntFactory
1206      *            the mngmnt factory
1207      */
1208     @Test
1209     void cascadeFromJavaManagementAPI(@Mocked ManagementFactory mngmntFactory) {
1210         CompilationMXBean compilation = ManagementFactory.getCompilationMXBean();
1211 
1212         assertNotNull(compilation);
1213         assertNull(compilation.getName());
1214     }
1215 
1216     /**
1217      * The Interface AnInterface.
1218      */
1219     public interface AnInterface {
1220         /**
1221          * Gets the package private class.
1222          *
1223          * @return the package private class
1224          */
1225         NonPublicTestedClass getPackagePrivateClass();
1226     }
1227 
1228     /**
1229      * Cascade from method in public interface returning package private type.
1230      *
1231      * @param mock
1232      *            the mock
1233      */
1234     @Test
1235     void cascadeFromMethodInPublicInterfaceReturningPackagePrivateType(@Mocked AnInterface mock) {
1236         NonPublicTestedClass ret = mock.getPackagePrivateClass();
1237 
1238         assertNull(ret);
1239     }
1240 
1241     /**
1242      * The Class CustomException.
1243      */
1244     public static final class CustomException extends Throwable {
1245 
1246         private static final long serialVersionUID = 1L;
1247     }
1248 
1249     /**
1250      * The Class AClass.
1251      */
1252     static class AClass {
1253         /**
1254          * Gets the exception.
1255          *
1256          * @return the exception
1257          */
1258         CustomException getException() {
1259             return new CustomException();
1260         }
1261     }
1262 
1263     /**
1264      * Cascade from method returning A throwable subclass.
1265      *
1266      * @param mock
1267      *            the mock
1268      */
1269     @Test
1270     void cascadeFromMethodReturningAThrowableSubclass(@Mocked AClass mock) {
1271         CustomException t = mock.getException();
1272 
1273         assertNull(t);
1274     }
1275 
1276     /**
1277      * The Class First.
1278      */
1279     static class First {
1280         /**
1281          * Gets the second.
1282          *
1283          * @param <T>
1284          *            the generic type
1285          * @param aClass
1286          *            the a class
1287          *
1288          * @return the second
1289          */
1290         <T extends Second> T getSecond(@SuppressWarnings("unused") Class<T> aClass) {
1291             return null;
1292         }
1293     }
1294 
1295     /**
1296      * The Class Second.
1297      */
1298     static class Second {
1299         /**
1300          * Gets the something.
1301          *
1302          * @return the something
1303          */
1304         Runnable getSomething() {
1305             return null;
1306         }
1307     }
1308 
1309     /**
1310      * Cascade from method returning type provided by class parameter then from cascaded instance.
1311      *
1312      * @param first
1313      *            the first
1314      */
1315     @Test
1316     void cascadeFromMethodReturningTypeProvidedByClassParameterThenFromCascadedInstance(@Mocked First first) {
1317         Second second = first.getSecond(Second.class);
1318         Runnable runnable = second.getSomething();
1319 
1320         assertNotNull(runnable);
1321     }
1322 
1323 }