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