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.assertNotNull;
10  import static org.junit.jupiter.api.Assertions.assertNotSame;
11  import static org.junit.jupiter.api.Assertions.assertNull;
12  import static org.junit.jupiter.api.Assertions.assertSame;
13  
14  import java.io.Serializable;
15  import java.util.Date;
16  import java.util.List;
17  import java.util.concurrent.Callable;
18  
19  import mockit.integration.junit5.JMockitExtension;
20  
21  import org.junit.jupiter.api.MethodOrderer.MethodName;
22  import org.junit.jupiter.api.Test;
23  import org.junit.jupiter.api.TestMethodOrder;
24  import org.junit.jupiter.api.extension.ExtendWith;
25  
26  /**
27   * The Class CascadingWithGenericsTest.
28   */
29  @ExtendWith(JMockitExtension.class)
30  @TestMethodOrder(MethodName.class)
31  class CascadingWithGenericsTest {
32  
33      /**
34       * The Class Foo.
35       */
36      static class Foo {
37  
38          /**
39           * Return type with wildcard.
40           *
41           * @return the callable
42           */
43          Callable<?> returnTypeWithWildcard() {
44              return null;
45          }
46  
47          /**
48           * Return type with bounded type variable.
49           *
50           * @param <RT>
51           *            the generic type
52           *
53           * @return the rt
54           */
55          <RT extends Baz> RT returnTypeWithBoundedTypeVariable() {
56              return null;
57          }
58  
59          /**
60           * Generic method with non mockable bounded type variable and class parameter.
61           *
62           * @param <N>
63           *            the number type
64           * @param c
65           *            the c
66           *
67           * @return the n
68           */
69          <N extends Number> N genericMethodWithNonMockableBoundedTypeVariableAndClassParameter(
70                  @SuppressWarnings("unused") Class<N> c) {
71              return null;
72          }
73  
74          /**
75           * Generic method with bounded type variable and class parameter.
76           *
77           * @param <RT>
78           *            the generic type
79           * @param cl
80           *            the cl
81           *
82           * @return the rt
83           */
84          <RT extends Bar> RT genericMethodWithBoundedTypeVariableAndClassParameter(
85                  @SuppressWarnings("unused") Class<RT> cl) {
86              return null;
87          }
88  
89          /**
90           * Return type with multiple type variables.
91           *
92           * @param <T1>
93           *            the generic type
94           * @param <T2>
95           *            the generic type
96           *
97           * @return the pair
98           */
99          <T1 extends Baz, T2 extends List<? extends Number>> Pair<T1, T2> returnTypeWithMultipleTypeVariables() {
100             return null;
101         }
102 
103         /**
104          * Return generic type with type argument.
105          *
106          * @return the callable
107          */
108         Callable<Baz> returnGenericTypeWithTypeArgument() {
109             return null;
110         }
111 
112         /**
113          * Bar.
114          *
115          * @return the bar
116          */
117         Bar bar() {
118             return null;
119         }
120     }
121 
122     /**
123      * The Interface Pair.
124      *
125      * @param <K>
126      *            the key type
127      * @param <V>
128      *            the value type
129      */
130     @SuppressWarnings("unused")
131     public interface Pair<K, V> {
132     }
133 
134     /**
135      * The Class Bar.
136      */
137     static class Bar {
138 
139         /**
140          * Instantiates a new bar.
141          */
142         Bar() {
143             throw new RuntimeException();
144         }
145 
146         /**
147          * Do something.
148          *
149          * @return the int
150          */
151         int doSomething() {
152             return 1;
153         }
154 
155         /**
156          * Static method.
157          *
158          * @return the string
159          */
160         static String staticMethod() {
161             return "notMocked";
162         }
163     }
164 
165     /**
166      * The Class SubBar.
167      */
168     static final class SubBar extends Bar {
169     }
170 
171     /**
172      * The Interface Baz.
173      */
174     public interface Baz {
175         /**
176          * Gets the date.
177          *
178          * @return the date
179          */
180         Date getDate();
181     }
182 
183     /**
184      * Cascade one level during replay.
185      *
186      * @param foo
187      *            the foo
188      */
189     @Test
190     void cascadeOneLevelDuringReplay(@Mocked Foo foo) {
191         assertNotNull(foo.returnTypeWithWildcard());
192         assertNotNull(foo.returnTypeWithBoundedTypeVariable());
193 
194         Pair<Baz, List<Integer>> x = foo.returnTypeWithMultipleTypeVariables();
195         assertNotNull(x);
196     }
197 
198     /**
199      * Cascade one level during record.
200      *
201      * @param action
202      *            the action
203      * @param mockFoo
204      *            the mock foo
205      */
206     @Test
207     void cascadeOneLevelDuringRecord(@Mocked Callable<String> action, @Mocked Foo mockFoo) {
208         Foo foo = new Foo();
209         Callable<?> cascaded = foo.returnTypeWithWildcard();
210 
211         assertSame(action, cascaded);
212     }
213 
214     /**
215      * Cascade two levels during record.
216      *
217      * @param mockFoo
218      *            the mock foo
219      */
220     @Test
221     void cascadeTwoLevelsDuringRecord(@Mocked final Foo mockFoo) {
222         final Date now = new Date();
223 
224         new Expectations() {
225             {
226                 mockFoo.returnTypeWithBoundedTypeVariable().getDate();
227                 result = now;
228             }
229         };
230 
231         Foo foo = new Foo();
232         assertSame(now, foo.returnTypeWithBoundedTypeVariable().getDate());
233     }
234 
235     /**
236      * The Class GenericFoo.
237      *
238      * @param <T>
239      *            the generic type
240      * @param <U>
241      *            the generic type
242      */
243     static class GenericFoo<T, U extends Bar> {
244 
245         /**
246          * Return type with unbounded type variable.
247          *
248          * @return the t
249          */
250         T returnTypeWithUnboundedTypeVariable() {
251             return null;
252         }
253 
254         /**
255          * Return type with bounded type variable.
256          *
257          * @return the u
258          */
259         U returnTypeWithBoundedTypeVariable() {
260             return null;
261         }
262     }
263 
264     /**
265      * Cascade generic methods.
266      *
267      * @param foo
268      *            the foo
269      */
270     @Test
271     void cascadeGenericMethods(@Mocked GenericFoo<Baz, SubBar> foo) {
272         Baz t = foo.returnTypeWithUnboundedTypeVariable();
273         assertNotNull(t);
274 
275         SubBar u = foo.returnTypeWithBoundedTypeVariable();
276         assertNotNull(u);
277     }
278 
279     /**
280      * The Class A.
281      */
282     static class A {
283         /**
284          * Gets the b.
285          *
286          * @return the b
287          */
288         B<?> getB() {
289             return null;
290         }
291     }
292 
293     /**
294      * The Class B.
295      *
296      * @param <T>
297      *            the generic type
298      */
299     static class B<T> {
300         /**
301          * Gets the value.
302          *
303          * @return the value
304          */
305         T getValue() {
306             return null;
307         }
308     }
309 
310     /**
311      * Cascade on method returning A parameterized class with A generic method.
312      *
313      * @param a
314      *            the a
315      */
316     @Test
317     void cascadeOnMethodReturningAParameterizedClassWithAGenericMethod(@Injectable final A a) {
318         new Expectations() {
319             {
320                 a.getB().getValue();
321                 result = "test";
322             }
323         };
324 
325         assertEquals("test", a.getB().getValue());
326     }
327 
328     /**
329      * The Class C.
330      *
331      * @param <T>
332      *            the generic type
333      */
334     @SuppressWarnings("unused")
335     static class C<T> {
336     }
337 
338     /**
339      * The Class D.
340      */
341     static class D extends C<Foo> {
342         /**
343          * Do something.
344          *
345          * @param <T>
346          *            the generic type
347          *
348          * @return the t
349          */
350         <T extends Bar> T doSomething() {
351             return null;
352         }
353     }
354 
355     /**
356      * Cascade from generic method using type parameter of same name as type parameter from base class.
357      *
358      * @param mock
359      *            the mock
360      */
361     @Test
362     void cascadeFromGenericMethodUsingTypeParameterOfSameNameAsTypeParameterFromBaseClass(@Mocked D mock) {
363         Bar cascaded = mock.doSomething();
364 
365         assertNotNull(cascaded);
366     }
367 
368     /**
369      * The Class Factory.
370      */
371     static class Factory {
372 
373         /**
374          * Bar.
375          *
376          * @param <T>
377          *            the generic type
378          *
379          * @return the t
380          */
381         static <T extends Bar> T bar() {
382             return null;
383         }
384 
385         /**
386          * Bar.
387          *
388          * @param <T>
389          *            the generic type
390          * @param c
391          *            the c
392          *
393          * @return the t
394          */
395         static <T extends Bar> T bar(@SuppressWarnings("UnusedParameters") Class<T> c) {
396             return null;
397         }
398 
399         /**
400          * Static init.
401          *
402          * @return the with static init
403          */
404         WithStaticInit staticInit() {
405             return null;
406         }
407     }
408 
409     /**
410      * The Class WithStaticInit.
411      */
412     static class WithStaticInit {
413 
414         /** The Constant T. */
415         static final Bar T = Factory.bar();
416 
417         /** The Constant S. */
418         static final SubBar S = Factory.bar(SubBar.class);
419     }
420 
421     /**
422      * Cascade during static initialization of cascaded class.
423      *
424      * @param mock
425      *            the mock
426      */
427     @Test
428     void cascadeDuringStaticInitializationOfCascadedClass(@Mocked Factory mock) {
429         assertNotNull(mock.staticInit());
430         assertNotNull(WithStaticInit.T);
431         assertNotNull(WithStaticInit.S);
432     }
433 
434     /**
435      * Cascade from generic method where concrete return type is given by class parameter but is not mockable.
436      *
437      * @param foo
438      *            the foo
439      */
440     @Test
441     void cascadeFromGenericMethodWhereConcreteReturnTypeIsGivenByClassParameterButIsNotMockable(@Mocked Foo foo) {
442         Integer n = foo.genericMethodWithNonMockableBoundedTypeVariableAndClassParameter(Integer.class);
443 
444         assertNotNull(n);
445     }
446 
447     /**
448      * Cascade from generic method where concrete return type is given by class parameter.
449      *
450      * @param foo
451      *            the foo
452      */
453     @Test
454     void cascadeFromGenericMethodWhereConcreteReturnTypeIsGivenByClassParameter(@Mocked Foo foo) {
455         SubBar subBar = foo.genericMethodWithBoundedTypeVariableAndClassParameter(SubBar.class);
456 
457         assertNotNull(subBar);
458     }
459 
460     /**
461      * Cascade from generic method whose return type comes from parameter on owner type.
462      *
463      * @param foo
464      *            the foo
465      * @param cascadedBaz
466      *            the cascaded baz
467      *
468      * @throws Exception
469      *             the exception
470      */
471     @Test
472     void cascadeFromGenericMethodWhoseReturnTypeComesFromParameterOnOwnerType(@Mocked Foo foo,
473             @Mocked final Baz cascadedBaz) throws Exception {
474         final Date date = new Date();
475         new Expectations() {
476             {
477                 cascadedBaz.getDate();
478                 result = date;
479             }
480         };
481 
482         Callable<Baz> callable = foo.returnGenericTypeWithTypeArgument();
483         Baz baz = callable.call();
484 
485         assertSame(cascadedBaz, baz);
486         assertSame(date, baz.getDate());
487     }
488 
489     /**
490      * The Interface GenericInterface.
491      *
492      * @param <T>
493      *            the generic type
494      */
495     public interface GenericInterface<T> {
496         /**
497          * Save.
498          *
499          * @param <S>
500          *            the generic type
501          * @param entity
502          *            the entity
503          *
504          * @return the s
505          */
506         <S extends T> S save(S entity);
507     }
508 
509     /**
510      * The Interface ConcreteInterface.
511      */
512     public interface ConcreteInterface extends GenericInterface<Foo> {
513     }
514 
515     /**
516      * Cascading from generic method whose type parameter extends another.
517      *
518      * @param mock
519      *            the mock
520      */
521     @Test
522     void cascadingFromGenericMethodWhoseTypeParameterExtendsAnother(@Mocked ConcreteInterface mock) {
523         Foo value = new Foo();
524 
525         Foo saved = mock.save(value);
526 
527         assertNotNull(saved);
528         assertNotSame(value, saved);
529     }
530 
531     /**
532      * The Interface GenericInterfaceWithBoundedTypeParameter.
533      *
534      * @param <B>
535      *            the generic type
536      */
537     public interface GenericInterfaceWithBoundedTypeParameter<B extends Serializable> {
538         /**
539          * Gets the.
540          *
541          * @param id
542          *            the id
543          *
544          * @return the b
545          */
546         B get(int id);
547     }
548 
549     /**
550      * Cascade from method returning A type variable.
551      *
552      * @param <T>
553      *            the generic type
554      * @param mock
555      *            the mock
556      */
557     @Test
558     <T extends Serializable> void cascadeFromMethodReturningATypeVariable(
559             @Mocked final GenericInterfaceWithBoundedTypeParameter<T> mock) {
560         new Expectations() {
561             {
562                 mock.get(1);
563                 result = "test";
564                 mock.get(2);
565                 result = null;
566             }
567         };
568 
569         assertEquals("test", mock.get(1));
570         assertNull(mock.get(2));
571     }
572 
573     /**
574      * The Class TypeWithUnusedTypeParameterInGenericMethod.
575      */
576     static class TypeWithUnusedTypeParameterInGenericMethod {
577         /**
578          * Foo.
579          *
580          * @param <U>
581          *            the generic type
582          *
583          * @return the foo
584          */
585         @SuppressWarnings("unused")
586         <U> Foo foo() {
587             return null;
588         }
589     }
590 
591     /**
592      * Cascade from method having unused type parameter.
593      *
594      * @param mock
595      *            the mock
596      */
597     @Test
598     void cascadeFromMethodHavingUnusedTypeParameter(@Mocked TypeWithUnusedTypeParameterInGenericMethod mock) {
599         Foo foo = mock.foo();
600         Bar bar = foo.bar();
601         assertNotNull(bar);
602     }
603 
604     /**
605      * Cascade from generic method whose return type resolves to another generic type.
606      *
607      * @param mock
608      *            the mock
609      */
610     @Test
611     void cascadeFromGenericMethodWhoseReturnTypeResolvesToAnotherGenericType(@Mocked B<C<?>> mock) {
612         C<?> c = mock.getValue();
613 
614         assertNotNull(c);
615     }
616 
617     /**
618      * The Interface BaseGenericInterface.
619      *
620      * @param <B>
621      *            the generic type
622      */
623     public interface BaseGenericInterface<B> {
624         /**
625          * Generic method.
626          *
627          * @return the b
628          */
629         B genericMethod();
630     }
631 
632     /**
633      * The Interface GenericSubInterface.
634      *
635      * @param <S>
636      *            the generic type
637      */
638     public interface GenericSubInterface<S> extends BaseGenericInterface<S> {
639     }
640 
641     /**
642      * The Interface NonGenericInterface.
643      */
644     public interface NonGenericInterface extends GenericSubInterface<Bar> {
645     }
646 
647     /**
648      * Cascade from generic method defined two levels deep in inheritance hierarchy.
649      *
650      * @param mock
651      *            the mock
652      */
653     @Test
654     void cascadeFromGenericMethodDefinedTwoLevelsDeepInInheritanceHierarchy(@Mocked NonGenericInterface mock) {
655         Bar cascadedResult = mock.genericMethod();
656 
657         assertNotNull(cascadedResult);
658     }
659 
660     /**
661      * The Interface NonPublicInterfaceWithGenericMethod.
662      */
663     interface NonPublicInterfaceWithGenericMethod {
664         /**
665          * Do something.
666          *
667          * @param <T>
668          *            the generic type
669          *
670          * @return the t
671          */
672         <T extends Runnable> T doSomething();
673     }
674 
675     /**
676      * Cascade from generic method of non public interface.
677      *
678      * @param mock
679      *            the mock
680      */
681     @Test
682     void cascadeFromGenericMethodOfNonPublicInterface(@Mocked NonPublicInterfaceWithGenericMethod mock) {
683         Runnable result = mock.doSomething();
684 
685         assertNotNull(result);
686     }
687 
688     /**
689      * The Interface FactoryInterface.
690      */
691     public interface FactoryInterface {
692         /**
693          * Generic with class.
694          *
695          * @param <T>
696          *            the generic type
697          * @param type
698          *            the type
699          *
700          * @return the t
701          */
702         <T> T genericWithClass(Class<T> type);
703     }
704 
705     /**
706      * Cascade from generic method with class parameter of mocked interface.
707      *
708      * @param mock
709      *            the mock
710      */
711     @Test
712     void cascadeFromGenericMethodWithClassParameterOfMockedInterface(@Mocked FactoryInterface mock) {
713         Foo cascaded = mock.genericWithClass(Foo.class);
714 
715         assertNotNull(cascaded);
716     }
717 
718     /**
719      * The Class Outer.
720      *
721      * @param <T>
722      *            the generic type
723      */
724     @SuppressWarnings("unused")
725     static class Outer<T> {
726         /**
727          * The Class Inner.
728          */
729         class Inner {
730         }
731     }
732 
733     /**
734      * The Class Client.
735      */
736     static class Client {
737         /**
738          * Do something.
739          *
740          * @return the outer. inner
741          */
742         Outer<String>.Inner doSomething() {
743             return null;
744         }
745     }
746 
747     /**
748      * Cascade from method returning inner instance of generic class.
749      *
750      * @param mock
751      *            the mock
752      */
753     @Test
754     void cascadeFromMethodReturningInnerInstanceOfGenericClass(@Mocked final Client mock) {
755         final Outer<?>.Inner innerInstance = new Outer().new Inner();
756 
757         new Expectations() {
758             {
759                 mock.doSomething();
760                 result = innerInstance;
761             }
762         };
763 
764         assertSame(innerInstance, mock.doSomething());
765     }
766 
767     /**
768      * The Class SubB.
769      *
770      * @param <T>
771      *            the generic type
772      */
773     static class SubB<T> extends B<T> {
774     }
775 
776     /**
777      * The Class ClassWithMethodReturningGenericClassInstance.
778      */
779     static class ClassWithMethodReturningGenericClassInstance {
780         /**
781          * Do something.
782          *
783          * @return the sub B
784          */
785         SubB<C<?>> doSomething() {
786             return null;
787         }
788     }
789 
790     /**
791      * Cascade from method returning instance of generic subclass then from generic method of generic base class.
792      *
793      * @param mock
794      *            the mock
795      */
796     @Test
797     void cascadeFromMethodReturningInstanceOfGenericSubclassThenFromGenericMethodOfGenericBaseClass(
798             @Mocked ClassWithMethodReturningGenericClassInstance mock) {
799         SubB<C<?>> cascade1 = mock.doSomething();
800         C<?> cascade2 = cascade1.getValue();
801 
802         assertNotNull(cascade2);
803     }
804 
805     /**
806      * The Interface InterfaceWithGenericMethod.
807      *
808      * @param <T>
809      *            the generic type
810      */
811     public interface InterfaceWithGenericMethod<T> {
812         /**
813          * Generic method.
814          *
815          * @return the t
816          */
817         @SuppressWarnings("unused")
818         T genericMethod();
819     }
820 
821     /**
822      * The Class BaseClass.
823      */
824     static class BaseClass {
825         /**
826          * Generic method.
827          *
828          * @return the bar
829          */
830         public Bar genericMethod() {
831             return null;
832         }
833     }
834 
835     /**
836      * The Class SubClass.
837      */
838     static class SubClass extends BaseClass implements InterfaceWithGenericMethod<Bar> {
839     }
840 
841     /**
842      * Cascade from generic interface method implemented in base class of mocked sub class.
843      *
844      * @param mock
845      *            the mock
846      */
847     @Test
848     void cascadeFromGenericInterfaceMethodImplementedInBaseClassOfMockedSubClass(@Mocked SubClass mock) {
849         Bar cascaded = mock.genericMethod();
850         assertNotNull(cascaded);
851     }
852 }