View Javadoc
1   package mockit;
2   
3   import static java.util.Arrays.asList;
4   
5   import static org.junit.jupiter.api.Assertions.assertEquals;
6   import static org.junit.jupiter.api.Assertions.assertNotNull;
7   import static org.junit.jupiter.api.Assertions.assertNull;
8   import static org.junit.jupiter.api.Assertions.assertSame;
9   
10  import java.io.Serializable;
11  import java.lang.reflect.Type;
12  import java.util.Dictionary;
13  import java.util.List;
14  import java.util.Map;
15  import java.util.concurrent.Callable;
16  
17  import org.junit.jupiter.api.Test;
18  
19  /**
20   * The Class GenericMockedTypesTest.
21   */
22  final class GenericMockedTypesTest {
23  
24      /** The mock 2. */
25      @Mocked
26      Callable<Integer> mock2;
27  
28      /**
29       * Mock generic interfaces.
30       *
31       * @param mock1
32       *            the mock 1
33       *
34       * @throws Exception
35       *             the exception
36       */
37      @Test
38      void mockGenericInterfaces(@Mocked final Callable<?> mock1) throws Exception {
39          new Expectations() {
40              {
41                  mock1.call();
42                  result = "mocked";
43                  mock2.call();
44                  result = 123;
45              }
46          };
47  
48          assertEquals("mocked", mock1.call());
49          assertEquals(123, mock2.call().intValue());
50      }
51  
52      /**
53       * Obtain generic superclass from class generated for non generic interface.
54       *
55       * @param mock
56       *            the mock
57       */
58      @Test
59      void obtainGenericSuperclassFromClassGeneratedForNonGenericInterface(@Mocked Runnable mock) {
60          Class<?> generatedClass = mock.getClass();
61          Type genericSuperClass = generatedClass.getGenericSuperclass();
62  
63          // At one time, a "GenericSignatureFormatError: Signature Parse error: expected a class type
64          // Remaining input: nullLjava/lang/Runnable;" would occur.
65          assertSame(Object.class, genericSuperClass);
66      }
67  
68      /**
69       * Mock generic abstract class.
70       *
71       * @param mock
72       *            the mock
73       */
74      @Test
75      void mockGenericAbstractClass(@Mocked final Dictionary<Integer, String> mock) {
76          new Expectations() {
77              {
78                  mock.put(123, "test");
79                  result = "mocked";
80              }
81          };
82  
83          assertEquals("mocked", mock.put(123, "test"));
84      }
85  
86      @Test
87      public void mockRawMapInterface(@SuppressWarnings("rawtypes") @Mocked final Map rawMap) {
88          new Expectations() {
89              {
90                  rawMap.get("test");
91                  result = new Object();
92              }
93          };
94  
95          Object value = rawMap.get("test");
96          assertNotNull(value);
97      }
98  
99      /**
100      * The Interface InterfaceWithMethodParametersMixingGenericTypesAndArrays.
101      */
102     public interface InterfaceWithMethodParametersMixingGenericTypesAndArrays {
103 
104         /**
105          * Do something.
106          *
107          * @param <T>
108          *            the generic type
109          * @param i
110          *            the i
111          * @param b
112          *            the b
113          */
114         <T> void doSomething(int[] i, T b);
115 
116         /**
117          * Do something.
118          *
119          * @param pc
120          *            the pc
121          * @param ii
122          *            the ii
123          */
124         void doSomething(Callable<int[]> pc, int[] ii);
125 
126         /**
127          * Do something.
128          *
129          * @param pc
130          *            the pc
131          * @param i
132          *            the i
133          * @param currencies
134          *            the currencies
135          * @param ii
136          *            the ii
137          */
138         void doSomething(Callable<String> pc, int[] i, boolean[] currencies, int[] ii);
139     }
140 
141     /**
142      * Mock methods having generics and arrays.
143      *
144      * @param mock
145      *            the mock
146      */
147     @Test
148     void mockMethodsHavingGenericsAndArrays(@Mocked InterfaceWithMethodParametersMixingGenericTypesAndArrays mock) {
149         mock.doSomething((Callable<int[]>) null, new int[] { 1, 2 });
150         mock.doSomething(null, new int[] { 1, 2 }, null, new int[] { 3, 4, 5 });
151     }
152 
153     /**
154      * The Interface NonGenericInterfaceWithGenericMethods.
155      */
156     public interface NonGenericInterfaceWithGenericMethods {
157 
158         /**
159          * Generic method with unbounded return type.
160          *
161          * @param <T>
162          *            the generic type
163          *
164          * @return the t
165          */
166         <T> T genericMethodWithUnboundedReturnType();
167 
168         /**
169          * Generic method with bounded return type.
170          *
171          * @param <T>
172          *            the generic type
173          *
174          * @return the t
175          */
176         <T extends CharSequence> T genericMethodWithBoundedReturnType();
177     }
178 
179     /**
180      * Result from generic methods of non generic interface.
181      *
182      * @param mock
183      *            the mock
184      */
185     @Test
186     void resultFromGenericMethodsOfNonGenericInterface(@Mocked final NonGenericInterfaceWithGenericMethods mock) {
187         new Expectations() {
188             {
189                 mock.genericMethodWithUnboundedReturnType();
190                 result = 123;
191                 mock.genericMethodWithBoundedReturnType();
192                 result = "test";
193             }
194         };
195 
196         Object v1 = mock.genericMethodWithUnboundedReturnType();
197         assertEquals(123, v1);
198 
199         Object v2 = mock.genericMethodWithBoundedReturnType();
200         assertEquals("test", v2);
201     }
202 
203     /**
204      * The Class Item.
205      */
206     static class Item implements Serializable {
207 
208         private static final long serialVersionUID = 1L;
209     }
210 
211     /**
212      * The Class GenericContainer.
213      *
214      * @param <T>
215      *            the generic type
216      */
217     static class GenericContainer<T extends Serializable> {
218         /**
219          * Gets the item.
220          *
221          * @return the item
222          */
223         final T getItem() {
224             return null;
225         }
226     }
227 
228     /**
229      * Creates the first level cascaded mock from type parameter.
230      *
231      * @param mockContainer
232      *            the mock container
233      */
234     @Test
235     void createFirstLevelCascadedMockFromTypeParameter(@Mocked GenericContainer<Item> mockContainer) {
236         Serializable mock = mockContainer.getItem();
237 
238         assertSame(Item.class, mock.getClass());
239     }
240 
241     /**
242      * The Class Factory1.
243      */
244     static class Factory1 {
245         /**
246          * Gets the container.
247          *
248          * @return the container
249          */
250         static GenericContainer<Item> getContainer() {
251             return null;
252         }
253     }
254 
255     /**
256      * Creates the second level cascaded mock from type parameter in generic method resolved from first level return
257      * type.
258      *
259      * @param mockFactory
260      *            the mock factory
261      */
262     @Test
263     void createSecondLevelCascadedMockFromTypeParameterInGenericMethodResolvedFromFirstLevelReturnType(
264             @Mocked Factory1 mockFactory) {
265         GenericContainer<Item> mockContainer = Factory1.getContainer();
266         Serializable cascadedMock = mockContainer.getItem();
267 
268         assertNotNull(cascadedMock);
269         assertSame(Item.class, cascadedMock.getClass());
270     }
271 
272     /**
273      * The Class ConcreteContainer.
274      */
275     static class ConcreteContainer extends GenericContainer<Item> {
276     }
277 
278     /**
279      * The Class Factory2.
280      */
281     static class Factory2 {
282         /**
283          * Gets the container.
284          *
285          * @return the container
286          */
287         ConcreteContainer getContainer() {
288             return null;
289         }
290     }
291 
292     /**
293      * Creates the second level cascaded mock from type parameter in base type of method return.
294      *
295      * @param mockFactory
296      *            the mock factory
297      */
298     @Test
299     void createSecondLevelCascadedMockFromTypeParameterInBaseTypeOfMethodReturn(@Mocked Factory2 mockFactory) {
300         ConcreteContainer mockContainer = mockFactory.getContainer();
301         Serializable cascadedMock = mockContainer.getItem();
302 
303         assertSame(Item.class, cascadedMock.getClass());
304     }
305 
306     /**
307      * The Class Collaborator.
308      */
309     static class Collaborator {
310         /**
311          * Do something.
312          *
313          * @return the runnable
314          */
315         Runnable doSomething() {
316             return null;
317         }
318     }
319 
320     /**
321      * The Class Collaborator2.
322      */
323     static class Collaborator2 {
324     }
325 
326     /**
327      * Cascading class with name starting with another mocked class.
328      *
329      * @param regularMock
330      *            the regular mock
331      * @param cascadingMock
332      *            the cascading mock
333      */
334     @Test
335     void cascadingClassWithNameStartingWithAnotherMockedClass(@Mocked final Collaborator regularMock,
336             @Mocked Collaborator2 cascadingMock) {
337         new Expectations() {
338             {
339                 regularMock.doSomething();
340             }
341         };
342 
343         assertNotNull(regularMock.doSomething());
344     }
345 
346     /**
347      * The Interface InterfaceWithBoundedTypeParameter.
348      *
349      * @param <T>
350      *            the generic type
351      */
352     public interface InterfaceWithBoundedTypeParameter<T extends Runnable> {
353         /**
354          * Gets the foo.
355          *
356          * @return the foo
357          */
358         T getFoo();
359     }
360 
361     /**
362      * Creates the cascaded mock from generic interface method which returns bounded type parameter.
363      *
364      * @param mock
365      *            the mock
366      */
367     @Test
368     void createCascadedMockFromGenericInterfaceMethodWhichReturnsBoundedTypeParameter(
369             @Mocked InterfaceWithBoundedTypeParameter<?> mock) {
370         Runnable foo = mock.getFoo();
371         assertNotNull(foo);
372         foo.run();
373     }
374 
375     /**
376      * The Interface InterfaceWhichExtendsInterfaceWithBoundedTypeParameter.
377      *
378      * @param <T>
379      *            the generic type
380      */
381     public interface InterfaceWhichExtendsInterfaceWithBoundedTypeParameter<T extends Runnable>
382             extends InterfaceWithBoundedTypeParameter<T> {
383     }
384 
385     /**
386      * Creates the cascaded mock from generic method defined in super interface with bounded type parameter.
387      *
388      * @param mock
389      *            the mock
390      */
391     @Test
392     void createCascadedMockFromGenericMethodDefinedInSuperInterfaceWithBoundedTypeParameter(
393             @Mocked InterfaceWhichExtendsInterfaceWithBoundedTypeParameter<?> mock) {
394         Runnable foo = mock.getFoo();
395         assertNotNull(foo);
396         foo.run();
397     }
398 
399     /**
400      * The Class Abc.
401      */
402     static class Abc {
403     }
404 
405     /**
406      * The Class GenericBase.
407      *
408      * @param <T>
409      *            the generic type
410      */
411     static class GenericBase<T> {
412         /**
413          * Do something.
414          *
415          * @return the t
416          */
417         T doSomething() {
418             return null;
419         }
420     }
421 
422     /**
423      * The Class GenericSubclass.
424      *
425      * @param <T>
426      *            the generic type
427      */
428     static class GenericSubclass<T> extends GenericBase<T> {
429         /**
430          * Gets the abc.
431          *
432          * @return the abc
433          */
434         T getAbc() {
435             return null;
436         }
437     }
438 
439     /**
440      * Creates the cascaded mock from generic subclass having same type parameter name as base class.
441      *
442      * @param mock
443      *            the mock
444      */
445     @Test
446     void createCascadedMockFromGenericSubclassHavingSameTypeParameterNameAsBaseClass(
447             @Mocked GenericSubclass<Abc> mock) {
448         Abc abc = mock.getAbc();
449         assertNotNull(abc);
450     }
451 
452     /**
453      * Mock generic class having type argument of array type.
454      *
455      * @param mock
456      *            the mock
457      */
458     @Test
459     void mockGenericClassHavingTypeArgumentOfArrayType(@Mocked GenericBase<String[]> mock) {
460         String[] result = mock.doSomething();
461 
462         assertEquals(0, result.length);
463     }
464 
465     /**
466      * Mock generic class having type argument of array type with primitive component.
467      *
468      * @param mock
469      *            the mock
470      */
471     @Test
472     void mockGenericClassHavingTypeArgumentOfArrayTypeWithPrimitiveComponent(@Mocked GenericBase<int[]> mock) {
473         int[] result = mock.doSomething();
474 
475         assertEquals(0, result.length);
476     }
477 
478     /**
479      * Mock generic class having type argument of array type with 2 D primitive component.
480      *
481      * @param mock
482      *            the mock
483      */
484     @Test
485     void mockGenericClassHavingTypeArgumentOfArrayTypeWith2DPrimitiveComponent(@Mocked GenericBase<int[][]> mock) {
486         int[][] result = mock.doSomething();
487 
488         assertEquals(0, result.length);
489     }
490 
491     /**
492      * Mock generic class having type argument of array type with generic component.
493      *
494      * @param mock
495      *            the mock
496      */
497     @Test
498     void mockGenericClassHavingTypeArgumentOfArrayTypeWithGenericComponent(@Mocked GenericBase<List<?>[]> mock) {
499         List<?>[] result = mock.doSomething();
500 
501         assertEquals(0, result.length);
502     }
503 
504     /**
505      * The Class DerivedClass.
506      */
507     static final class DerivedClass extends GenericBase<Number[]> {
508     }
509 
510     /**
511      * Mock class extending A generic base class having type argument of array type.
512      *
513      * @param mock
514      *            the mock
515      */
516     @Test
517     void mockClassExtendingAGenericBaseClassHavingTypeArgumentOfArrayType(@Mocked DerivedClass mock) {
518         Number[] result = mock.doSomething();
519 
520         assertEquals(0, result.length);
521     }
522 
523     /**
524      * The Interface BaseGenericInterface.
525      *
526      * @param <V>
527      *            the value type
528      */
529     public interface BaseGenericInterface<V> {
530         /**
531          * Do something.
532          *
533          * @return the v
534          */
535         V doSomething();
536     }
537 
538     /**
539      * The Interface DerivedGenericInterface.
540      *
541      * @param <V>
542      *            the value type
543      */
544     public interface DerivedGenericInterface<V> extends BaseGenericInterface<List<V>> {
545         /**
546          * Do something else.
547          *
548          * @return the v
549          */
550         V doSomethingElse();
551     }
552 
553     /**
554      * Record generic interface method with return type given by type parameter dependent on another type parameter of
555      * same name.
556      *
557      * @param dep
558      *            the dep
559      */
560     @Test
561     void recordGenericInterfaceMethodWithReturnTypeGivenByTypeParameterDependentOnAnotherTypeParameterOfSameName(
562             @Mocked final DerivedGenericInterface<String> dep) {
563         final List<String> values = asList("a", "b");
564 
565         new Expectations() {
566             {
567                 dep.doSomething();
568                 result = values;
569                 dep.doSomethingElse();
570                 result = "Abc";
571             }
572         };
573 
574         List<String> resultFromBase = dep.doSomething();
575         String resultFromSub = dep.doSomethingElse();
576 
577         assertSame(values, resultFromBase);
578         assertEquals("Abc", resultFromSub);
579     }
580 
581     /**
582      * Mock generic type with generic multi dimensional array type argument.
583      *
584      * @param mock
585      *            the mock
586      */
587     @Test
588     void mockGenericTypeWithGenericMultiDimensionalArrayTypeArgument(@Mocked GenericBase<List<?>[][]> mock) {
589         List<?>[][] result = mock.doSomething();
590 
591         assertEquals(0, result.length);
592     }
593 
594     /**
595      * The Interface BaseInterface.
596      *
597      * @param <T>
598      *            the generic type
599      */
600     public interface BaseInterface<T> {
601         /**
602          * Do something.
603          *
604          * @param t
605          *            the t
606          */
607         void doSomething(T t);
608     }
609 
610     /**
611      * The Interface SubInterface.
612      */
613     public interface SubInterface extends BaseInterface<String> {
614 
615         /**
616          * Do something.
617          *
618          * @param s
619          *            the s
620          */
621         @SuppressWarnings("AbstractMethodOverridesAbstractMethod")
622         @Override
623         void doSomething(String s);
624     }
625 
626     /**
627      * Invoke generic base interface method that is overridden in mocked sub interface.
628      *
629      * @param mock
630      *            the mock
631      */
632     @Test
633     void invokeGenericBaseInterfaceMethodThatIsOverriddenInMockedSubInterface(@Mocked final SubInterface mock) {
634         @SuppressWarnings("UnnecessaryLocalVariable")
635         BaseInterface<String> base = mock;
636         base.doSomething("test");
637 
638         new Verifications() {
639             {
640                 mock.doSomething("test");
641             }
642         };
643     }
644 
645     /**
646      * The Class Outer.
647      *
648      * @param <T>
649      *            the generic type
650      */
651     public static class Outer<T> {
652 
653         /**
654          * The Class Inner.
655          */
656         public abstract class Inner {
657             /**
658              * Gets the some value.
659              *
660              * @return the some value
661              */
662             public abstract T getSomeValue();
663         }
664 
665         /**
666          * The Class SubInner.
667          */
668         public abstract class SubInner extends Inner {
669         }
670     }
671 
672     /**
673      * Mock inner class which uses type variable of outer class.
674      *
675      * @param mock
676      *            the mock
677      */
678     @Test
679     void mockInnerClassWhichUsesTypeVariableOfOuterClass(@Mocked Outer<String>.Inner mock) {
680         String in = mock.getSomeValue();
681         assertNull(in);
682     }
683 
684     /**
685      * Mock abstract sub class of inner class which uses type variable of outer class.
686      *
687      * @param mock
688      *            the mock
689      */
690     @Test
691     void mockAbstractSubClassOfInnerClassWhichUsesTypeVariableOfOuterClass(@Mocked Outer<String>.SubInner mock) {
692         String in = mock.getSomeValue();
693         assertNull(in);
694     }
695 
696     /**
697      * The Class T1.
698      */
699     static class T1 {
700     }
701 
702     /**
703      * The Class T2.
704      */
705     static class T2 {
706     }
707 
708     /**
709      * Cascade from generic method of second mocked generic type having different parameter type from first mocked type.
710      *
711      * @param mock1
712      *            the mock 1
713      * @param mock3
714      *            the mock 3
715      */
716     @Test
717     void cascadeFromGenericMethodOfSecondMockedGenericTypeHavingDifferentParameterTypeFromFirstMockedType(
718             @Mocked GenericBase<T1> mock1, @Mocked GenericBase<T2> mock3) {
719         T2 r = mock3.doSomething();
720         assertNotNull(r);
721     }
722 
723     /**
724      * The Class AClass.
725      */
726     static class AClass {
727 
728         /**
729          * Generic method.
730          *
731          * @param <R>
732          *            the generic type
733          *
734          * @return the r
735          */
736         <R> R genericMethod() {
737             return null;
738         }
739 
740         /**
741          * Generic method with parameter.
742          *
743          * @param <R>
744          *            the generic type
745          * @param value
746          *            the value
747          *
748          * @return the r
749          */
750         <R> R genericMethodWithParameter(R value) {
751             return value;
752         }
753 
754         /**
755          * Generic method with two type parameters.
756          *
757          * @param <R>
758          *            the generic type
759          * @param <S>
760          *            the generic type
761          * @param s
762          *            the s
763          *
764          * @return the r
765          */
766         <R, S> R genericMethodWithTwoTypeParameters(@SuppressWarnings("unused") S s) {
767             return null;
768         }
769     }
770 
771     /**
772      * Return null from generic method.
773      *
774      * @param mock
775      *            the mock
776      */
777     @Test
778     void returnNullFromGenericMethod(@Mocked AClass mock) {
779         String test1 = mock.genericMethod();
780         String test2 = mock.genericMethodWithParameter("test2");
781         String test3 = mock.genericMethodWithTwoTypeParameters(1);
782 
783         assertNull(test1);
784         assertNull(test2);
785         assertNull(test3);
786     }
787 }