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