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.assertTrue;
10  
11  import java.io.Serializable;
12  import java.util.Date;
13  import java.util.List;
14  
15  import org.junit.jupiter.api.BeforeEach;
16  import org.junit.jupiter.api.MethodOrderer.MethodName;
17  import org.junit.jupiter.api.Test;
18  import org.junit.jupiter.api.TestMethodOrder;
19  
20  /**
21   * The Class CascadingFieldTest.
22   */
23  @TestMethodOrder(MethodName.class)
24  final class CascadingFieldTest {
25  
26      /**
27       * The Class Foo.
28       */
29      static class Foo {
30  
31          /**
32           * Gets the bar.
33           *
34           * @return the bar
35           */
36          Bar getBar() {
37              return null;
38          }
39  
40          /**
41           * Global bar.
42           *
43           * @return the bar
44           */
45          static Bar globalBar() {
46              return null;
47          }
48  
49          /**
50           * Do something.
51           *
52           * @param s
53           *            the s
54           */
55          void doSomething(String s) {
56              throw new RuntimeException(s);
57          }
58  
59          /**
60           * Gets the int value.
61           *
62           * @return the int value
63           */
64          int getIntValue() {
65              return 1;
66          }
67  
68          /**
69           * Gets the boolean value.
70           *
71           * @return the boolean value
72           */
73          Boolean getBooleanValue() {
74              return true;
75          }
76  
77          /**
78           * Gets the string value.
79           *
80           * @return the string value
81           */
82          String getStringValue() {
83              return "abc";
84          }
85  
86          /**
87           * Gets the date.
88           *
89           * @return the date
90           */
91          public final Date getDate() {
92              return null;
93          }
94  
95          /**
96           * Gets the list.
97           *
98           * @return the list
99           */
100         final List<Integer> getList() {
101             return null;
102         }
103     }
104 
105     /**
106      * The Class Bar.
107      */
108     static class Bar {
109 
110         /**
111          * Instantiates a new bar.
112          */
113         Bar() {
114             throw new RuntimeException();
115         }
116 
117         /**
118          * Do something.
119          *
120          * @return the int
121          */
122         int doSomething() {
123             return 1;
124         }
125 
126         /**
127          * Checks if is done.
128          *
129          * @return true, if is done
130          */
131         boolean isDone() {
132             return false;
133         }
134 
135         /**
136          * Gets the short.
137          *
138          * @return the short
139          */
140         Short getShort() {
141             return 1;
142         }
143 
144         /**
145          * Gets the list.
146          *
147          * @return the list
148          */
149         List<?> getList() {
150             return null;
151         }
152 
153         /**
154          * Gets the baz.
155          *
156          * @return the baz
157          */
158         Baz getBaz() {
159             return null;
160         }
161 
162         /**
163          * Gets the task.
164          *
165          * @return the task
166          */
167         Runnable getTask() {
168             return null;
169         }
170     }
171 
172     /**
173      * The Class Baz.
174      */
175     static final class Baz {
176 
177         /** The e. */
178         final E e;
179 
180         /**
181          * Instantiates a new baz.
182          *
183          * @param e
184          *            the e
185          */
186         Baz(E e) {
187             this.e = e;
188         }
189 
190         /**
191          * Gets the e.
192          *
193          * @return the e
194          */
195         E getE() {
196             return e;
197         }
198 
199         /**
200          * Do something.
201          */
202         void doSomething() {
203         }
204     }
205 
206     /**
207      * The Enum E.
208      */
209     public enum E {
210         /** The a. */
211         A,
212         /** The b. */
213         B
214     }
215 
216     /**
217      * The Interface A.
218      */
219     public interface A {
220         /**
221          * Gets the b.
222          *
223          * @return the b
224          */
225         B getB();
226     }
227 
228     /**
229      * The Interface B.
230      */
231     public interface B {
232         /**
233          * Gets the c.
234          *
235          * @return the c
236          */
237         C getC();
238     }
239 
240     /**
241      * The Interface C.
242      */
243     public interface C {
244     }
245 
246     /** The foo. */
247     @Mocked
248     Foo foo;
249 
250     /** The a. */
251     @Mocked
252     A a;
253 
254     /**
255      * Record common expectations.
256      */
257     @BeforeEach
258     void recordCommonExpectations() {
259         new Expectations() {
260             {
261                 Bar bar = foo.getBar();
262                 minTimes = 0;
263                 bar.isDone();
264                 result = true;
265                 minTimes = 0;
266             }
267         };
268     }
269 
270     /**
271      * Obtain cascaded instances at all levels.
272      */
273     @Test
274     void obtainCascadedInstancesAtAllLevels() {
275         assertNotNull(foo.getBar());
276         assertNotNull(foo.getBar().getList());
277         assertNotNull(foo.getBar().getBaz());
278         assertNotNull(foo.getBar().getTask());
279 
280         B b = a.getB();
281         assertNotNull(b);
282         assertNotNull(b.getC());
283     }
284 
285     /**
286      * Obtain cascaded instances at all levels again.
287      */
288     @Test
289     void obtainCascadedInstancesAtAllLevelsAgain() {
290         Bar bar = foo.getBar();
291         assertNotNull(bar);
292         assertNotNull(bar.getList());
293         assertNotNull(bar.getBaz());
294         assertNotNull(bar.getTask());
295 
296         assertNotNull(a.getB());
297         assertNotNull(a.getB().getC());
298     }
299 
300     /**
301      * Cascade one level.
302      */
303     @Test
304     void cascadeOneLevel() {
305         assertTrue(foo.getBar().isDone());
306         assertEquals(0, foo.getBar().doSomething());
307         assertEquals(0, Foo.globalBar().doSomething());
308         assertNotSame(foo.getBar(), Foo.globalBar());
309         assertEquals(0, foo.getBar().getShort().intValue());
310 
311         foo.doSomething("test");
312         assertEquals(0, foo.getIntValue());
313         assertFalse(foo.getBooleanValue());
314         assertNull(foo.getStringValue());
315         assertNotNull(foo.getDate());
316         assertTrue(foo.getList().isEmpty());
317 
318         new Verifications() {
319             {
320                 foo.doSomething(anyString);
321             }
322         };
323     }
324 
325     /**
326      * Exercise cascading mock again.
327      */
328     @Test
329     void exerciseCascadingMockAgain() {
330         assertTrue(foo.getBar().isDone());
331     }
332 
333     /**
334      * Record unambiguous expectations producing different cascaded instances.
335      *
336      * @param foo1
337      *            the foo 1
338      * @param foo2
339      *            the foo 2
340      */
341     @Test
342     void recordUnambiguousExpectationsProducingDifferentCascadedInstances(@Mocked final Foo foo1,
343             @Mocked final Foo foo2) {
344         new Expectations() {
345             {
346                 Date c1 = foo1.getDate();
347                 Date c2 = foo2.getDate();
348                 assertNotSame(c1, c2);
349             }
350         };
351 
352         Date d1 = foo1.getDate();
353         Date d2 = foo2.getDate();
354         assertNotSame(d1, d2);
355     }
356 
357     /**
358      * Record ambiguous expectations on instance method producing the same cascaded instance.
359      */
360     @Test
361     void recordAmbiguousExpectationsOnInstanceMethodProducingTheSameCascadedInstance() {
362         new Expectations() {
363             {
364                 Bar c1 = foo.getBar();
365                 Bar c2 = foo.getBar();
366                 assertSame(c1, c2);
367             }
368         };
369 
370         Bar b1 = foo.getBar();
371         Bar b2 = foo.getBar();
372         assertSame(b1, b2);
373     }
374 
375     /**
376      * Record ambiguous expectations on static method producing the same cascaded instance.
377      */
378     @Test
379     void recordAmbiguousExpectationsOnStaticMethodProducingTheSameCascadedInstance() {
380         new Expectations() {
381             {
382                 Bar c1 = Foo.globalBar();
383                 Bar c2 = Foo.globalBar();
384                 assertSame(c1, c2);
385             }
386         };
387 
388         Bar b1 = Foo.globalBar();
389         Bar b2 = Foo.globalBar();
390         assertSame(b1, b2);
391     }
392 
393     /**
394      * Record ambiguous expectation with multiple cascading candidates followed by expectation recorded on first
395      * candidate.
396      *
397      * @param bar1
398      *            the bar 1
399      * @param bar2
400      *            the bar 2
401      */
402     @Test
403     void recordAmbiguousExpectationWithMultipleCascadingCandidatesFollowedByExpectationRecordedOnFirstCandidate(
404             @Injectable final Bar bar1, @Injectable Bar bar2) {
405         new Expectations() {
406             {
407                 foo.getBar();
408                 bar1.doSomething();
409             }
410         };
411 
412         foo.getBar();
413         bar1.doSomething();
414     }
415 
416     /**
417      * The Class AnotherFoo.
418      */
419     static final class AnotherFoo {
420         /**
421          * Gets the bar.
422          *
423          * @return the bar
424          */
425         Bar getBar() {
426             return null;
427         }
428     }
429 
430     /** The another foo. */
431     @Mocked
432     AnotherFoo anotherFoo;
433 
434     /**
435      * Cascading mock field.
436      */
437     @Test
438     void cascadingMockField() {
439         new Expectations() {
440             {
441                 anotherFoo.getBar().doSomething();
442                 result = 123;
443             }
444         };
445 
446         assertEquals(123, new AnotherFoo().getBar().doSomething());
447     }
448 
449     /**
450      * Cascading instance accessed from delegate method.
451      */
452     @Test
453     void cascadingInstanceAccessedFromDelegateMethod() {
454         new Expectations() {
455             {
456                 foo.getIntValue();
457                 result = new Delegate<Object>() {
458                     @Mock
459                     int delegate() {
460                         return foo.getBar().doSomething();
461                     }
462                 };
463             }
464         };
465 
466         assertEquals(0, foo.getIntValue());
467     }
468 
469     /** The baz creator and consumer. */
470     @Mocked
471     BazCreatorAndConsumer bazCreatorAndConsumer;
472 
473     /**
474      * The Class BazCreatorAndConsumer.
475      */
476     static class BazCreatorAndConsumer {
477 
478         /**
479          * Creates the.
480          *
481          * @return the baz
482          */
483         Baz create() {
484             return null;
485         }
486 
487         /**
488          * Consume.
489          *
490          * @param arg
491          *            the arg
492          */
493         void consume(Baz arg) {
494             arg.toString();
495         }
496     }
497 
498     /**
499      * Call method on non cascaded instance from custom argument matcher with cascaded instance also created.
500      */
501     @Test
502     void callMethodOnNonCascadedInstanceFromCustomArgumentMatcherWithCascadedInstanceAlsoCreated() {
503         Baz nonCascadedInstance = new Baz(E.A);
504         Baz cascadedInstance = bazCreatorAndConsumer.create();
505         assertNotSame(nonCascadedInstance, cascadedInstance);
506 
507         bazCreatorAndConsumer.consume(nonCascadedInstance);
508 
509         new Verifications() {
510             {
511                 bazCreatorAndConsumer.consume(with(new Delegate<Baz>() {
512                     @SuppressWarnings("unused")
513                     boolean matches(Baz actual) {
514                         return actual.getE() == E.A;
515                     }
516                 }));
517             }
518         };
519     }
520 
521     // Tests for cascaded instances obtained from generic methods //////////////////////////////////////////////////////
522 
523     /**
524      * The Class GenericBaseClass1.
525      *
526      * @param <T>
527      *            the generic type
528      */
529     static class GenericBaseClass1<T> {
530         /**
531          * Gets the value.
532          *
533          * @return the value
534          */
535         T getValue() {
536             return null;
537         }
538     }
539 
540     /**
541      * Cascade generic method from specialized generic class.
542      *
543      * @param mock
544      *            the mock
545      */
546     @Test
547     void cascadeGenericMethodFromSpecializedGenericClass(@Mocked GenericBaseClass1<C> mock) {
548         C value = mock.getValue();
549         assertNotNull(value);
550     }
551 
552     /**
553      * The Class ConcreteSubclass1.
554      */
555     static class ConcreteSubclass1 extends GenericBaseClass1<A> {
556     }
557 
558     /**
559      * Cascade generic method of concrete subclass which extends generic class.
560      *
561      * @param mock
562      *            the mock
563      */
564     @Test
565     void cascadeGenericMethodOfConcreteSubclassWhichExtendsGenericClass(@Mocked final ConcreteSubclass1 mock) {
566         new Expectations() {
567             {
568                 mock.getValue().getB().getC();
569                 result = new C() {
570                 };
571             }
572         };
573 
574         A value = mock.getValue();
575         assertNotNull(value);
576         B b = value.getB();
577         assertNotNull(b);
578         assertNotNull(b.getC());
579 
580         new FullVerifications() {
581             {
582                 mock.getValue().getB().getC();
583             }
584         };
585     }
586 
587     /**
588      * The Interface Ab.
589      */
590     interface Ab extends A {
591     }
592 
593     /**
594      * The Class GenericBaseClass2.
595      *
596      * @param <T>
597      *            the generic type
598      */
599     static class GenericBaseClass2<T extends A> {
600         /**
601          * Gets the value.
602          *
603          * @return the value
604          */
605         T getValue() {
606             return null;
607         }
608     }
609 
610     /**
611      * The Class ConcreteSubclass2.
612      */
613     static class ConcreteSubclass2 extends GenericBaseClass2<Ab> {
614     }
615 
616     /**
617      * Cascade generic method of subclass which extends generic class with upper bound using interface.
618      *
619      * @param mock
620      *            the mock
621      */
622     @Test
623     void cascadeGenericMethodOfSubclassWhichExtendsGenericClassWithUpperBoundUsingInterface(
624             @Mocked final ConcreteSubclass2 mock) {
625         Ab value = mock.getValue();
626         assertNotNull(value);
627         value.getB().getC();
628 
629         new Verifications() {
630             {
631                 mock.getValue().getB().getC();
632                 times = 1;
633             }
634         };
635     }
636 
637     /**
638      * Cascade generic method of subclass which extends generic class with upper bound only in verification block.
639      *
640      * @param mock
641      *            the mock
642      */
643     @Test
644     void cascadeGenericMethodOfSubclassWhichExtendsGenericClassWithUpperBoundOnlyInVerificationBlock(
645             @Mocked final ConcreteSubclass2 mock) {
646         new FullVerifications() {
647             {
648                 Ab value = mock.getValue();
649                 times = 0;
650                 B b = value.getB();
651                 times = 0;
652                 b.getC();
653                 times = 0;
654             }
655         };
656     }
657 
658     /**
659      * The Class Action.
660      */
661     static final class Action implements A {
662         @Override
663         public B getB() {
664             return null;
665         }
666     }
667 
668     /**
669      * The Class ActionHolder.
670      */
671     static final class ActionHolder extends GenericBaseClass2<Action> {
672     }
673 
674     /**
675      * Cascade generic method of subclass which extends generic class with upper bound using class.
676      *
677      * @param mock
678      *            the mock
679      */
680     @Test
681     void cascadeGenericMethodOfSubclassWhichExtendsGenericClassWithUpperBoundUsingClass(
682             @Mocked final ActionHolder mock) {
683         new Expectations() {
684             {
685                 mock.getValue().getB().getC();
686             }
687         };
688 
689         mock.getValue().getB().getC();
690     }
691 
692     /**
693      * The Class Base.
694      *
695      * @param <T>
696      *            the generic type
697      */
698     static class Base<T extends Serializable> {
699         /**
700          * Value.
701          *
702          * @return the t
703          */
704         @SuppressWarnings("unchecked")
705         T value() {
706             return (T) Long.valueOf(123);
707         }
708     }
709 
710     /**
711      * The Class Derived1.
712      */
713     static class Derived1 extends Base<Long> {
714     }
715 
716     /**
717      * The Class Derived2.
718      */
719     static class Derived2 extends Base<Long> {
720     }
721 
722     /**
723      * The Interface Factory1.
724      */
725     interface Factory1 {
726         /**
727          * Gets the 1.
728          *
729          * @return the 1
730          */
731         Derived1 get1();
732     }
733 
734     /**
735      * The Interface Factory2.
736      */
737     interface Factory2 {
738         /**
739          * Gets the 2.
740          *
741          * @return the 2
742          */
743         Derived2 get2();
744     }
745 
746     /** The factory 1. */
747     @Mocked
748     Factory1 factory1;
749 
750     /** The factory 2. */
751     @Mocked
752     Factory2 factory2;
753 
754     /**
755      * Use subclass mocked through cascading.
756      */
757     @Test
758     void useSubclassMockedThroughCascading() {
759         Derived1 d1 = factory1.get1(); // cascade-mocks Derived1 (per-instance)
760         Long v1 = d1.value();
761         assertNull(v1);
762 
763         Long v2 = new Derived1().value(); // new instance, not mocked
764         assertEquals(123, v2.longValue());
765     }
766 
767     /**
768      * Use subclass previously mocked through cascading while mocking sibling subclass.
769      *
770      * @param d2
771      *            the d 2
772      */
773     @Test
774     void useSubclassPreviouslyMockedThroughCascadingWhileMockingSiblingSubclass(@Injectable Derived2 d2) {
775         Long v1 = new Derived1().value();
776         assertEquals(123, v1.longValue());
777 
778         Long v2 = d2.value();
779         assertNull(v2);
780 
781         Long v3 = new Derived2().value();
782         assertEquals(123, v3.longValue());
783     }
784 }