View Javadoc
1   package mockit;
2   
3   import static org.junit.jupiter.api.Assertions.assertNotNull;
4   import static org.junit.jupiter.api.Assertions.assertNull;
5   import static org.junit.jupiter.api.Assertions.assertSame;
6   
7   import java.io.Serializable;
8   import java.util.HashMap;
9   import java.util.List;
10  import java.util.Map;
11  import java.util.concurrent.Callable;
12  
13  import org.junit.jupiter.api.Test;
14  
15  /**
16   * The Class TestedClassWithGenericsTest.
17   */
18  final class TestedClassWithGenericsTest {
19  
20      /**
21       * The Interface Collaborator.
22       *
23       * @param <T>
24       *            the generic type
25       */
26      public interface Collaborator<T> {
27          /**
28           * Gets the value.
29           *
30           * @return the value
31           */
32          T getValue();
33      }
34  
35      /**
36       * The Class SUTWithUnboundedTypeParameter.
37       *
38       * @param <T>
39       *            the generic type
40       */
41      static class SUTWithUnboundedTypeParameter<T> {
42  
43          /** The value. */
44          T value;
45  
46          /** The collaborator. */
47          final Collaborator<T> collaborator;
48  
49          /** The collaborators. */
50          final Iterable<Collaborator<T>> collaborators;
51  
52          Map<T, ?> values;
53  
54          /** The action 1. */
55          Callable<T> action1;
56  
57          /** The action 2. */
58          Callable<?> action2;
59  
60          /**
61           * Instantiates a new SUT with unbounded type parameter.
62           *
63           * @param c
64           *            the c
65           */
66          @SuppressWarnings("unused")
67          SUTWithUnboundedTypeParameter(Collaborator<T> c) {
68              collaborator = c;
69              collaborators = null;
70          }
71  
72          /**
73           * Instantiates a new SUT with unbounded type parameter.
74           *
75           * @param collaborators
76           *            the collaborators
77           * @param action
78           *            the action
79           */
80          @SuppressWarnings("unused")
81          SUTWithUnboundedTypeParameter(Iterable<Collaborator<T>> collaborators, Callable<String> action) {
82              collaborator = null;
83              this.collaborators = collaborators;
84              action2 = action;
85          }
86  
87          <V extends CharSequence & Serializable> SUTWithUnboundedTypeParameter(Map<T, V> values, Callable<?> action) {
88              collaborator = null;
89              collaborators = null;
90              this.values = values;
91              action2 = action;
92          }
93      }
94  
95      /** The tested 1. */
96      @Tested
97      SUTWithUnboundedTypeParameter<Integer> tested1;
98  
99      /** The number to inject. */
100     @Injectable
101     final Integer numberToInject = 123;
102 
103     /** The mock collaborator. */
104     @Injectable
105     Collaborator<Integer> mockCollaborator;
106 
107     /**
108      * Use SUT created with constructor of single generic parameter and with generic field injected from concrete
109      * injectables.
110      */
111     @Test
112     void useSUTCreatedWithConstructorOfSingleGenericParameterAndWithGenericFieldInjectedFromConcreteInjectables() {
113         assertSame(mockCollaborator, tested1.collaborator);
114         assertNull(tested1.collaborators);
115         assertSame(numberToInject, tested1.value);
116         assertNull(tested1.action1);
117         assertNull(tested1.action2);
118         assertNull(tested1.values);
119     }
120 
121     /**
122      * Use SUT instantiated with constructor having multiple generic parameters.
123      *
124      * @param collaborators
125      *            the collaborators
126      * @param mockAction1
127      *            the mock action 1
128      * @param action1
129      *            the action 1
130      */
131     @Test
132     void useSUTInstantiatedWithConstructorHavingMultipleGenericParameters(
133             @Injectable Iterable<Collaborator<Integer>> collaborators, @Injectable Callable<String> mockAction1,
134             @Injectable Callable<Integer> action1) {
135         assertNull(tested1.collaborator);
136         assertSame(collaborators, tested1.collaborators);
137         assertSame(mockAction1, tested1.action2);
138         assertSame(action1, tested1.action1);
139         assertSame(numberToInject, tested1.value);
140         assertNull(tested1.values);
141     }
142 
143     /**
144      * Use SUT instantiated with generic constructor parameters injected from concrete injectables.
145      *
146      * @param mockCollaborators
147      *            the mock collaborators
148      * @param mockAction
149      *            the mock action
150      */
151     @Test
152     void useSUTInstantiatedWithGenericConstructorParametersInjectedFromConcreteInjectables(
153             @Injectable Iterable<Collaborator<Integer>> mockCollaborators, @Injectable Callable<String> mockAction) {
154         assertNull(tested1.collaborator);
155         assertSame(mockCollaborators, tested1.collaborators);
156         assertNull(tested1.action1);
157         assertSame(mockAction, tested1.action2);
158         assertSame(numberToInject, tested1.value);
159         assertNull(tested1.values);
160     }
161 
162     /**
163      * The Class SUTWithGenericConstructor.
164      *
165      * @param <T>
166      *            the generic type
167      */
168     static class SUTWithGenericConstructor<T> {
169 
170         /** The values. */
171         final Map<T, ?> values;
172 
173         /**
174          * Instantiates a new SUT with generic constructor.
175          *
176          * @param <V>
177          *            the value type
178          * @param values
179          *            the values
180          */
181         @SuppressWarnings("unused")
182         <V extends CharSequence & Serializable> SUTWithGenericConstructor(Map<T, V> values) {
183             this.values = values;
184         }
185     }
186 
187     /** The map values. */
188     @Tested
189     final Map<Integer, String> mapValues = new HashMap<>();
190 
191     /** The tested 8. */
192     @Tested
193     SUTWithGenericConstructor<Integer> tested8;
194 
195     /**
196      * Use SUT instantiated with generic constructor.
197      */
198     @Test
199     void useSUTInstantiatedWithGenericConstructor() {
200         assertSame(mapValues, tested8.values);
201     }
202 
203     @Test
204     public void useSUTInstantiatedWithGenericConstructor(@Injectable Callable<?> mockAction,
205             @Injectable Map<Integer, String> mockValues) {
206         assertNull(tested1.collaborator);
207         assertNull(tested1.collaborators);
208         assertSame(mockValues, tested1.values);
209         assertNull(tested1.action1);
210         assertSame(mockAction, tested1.action2);
211         assertSame(numberToInject, tested1.value);
212     }
213 
214     /**
215      * The Class GenericClass.
216      *
217      * @param <T>
218      *            the generic type
219      */
220     static class GenericClass<T> {
221         /** The value. */
222         T value;
223     }
224 
225     /**
226      * The Class SUTWithBoundedTypeParameter.
227      *
228      * @param <N>
229      *            the number type
230      * @param <C>
231      *            the generic type
232      */
233     static class SUTWithBoundedTypeParameter<N extends Number, C extends CharSequence> {
234 
235         /** The text value. */
236         C textValue;
237 
238         /** The number value. */
239         N numberValue;
240 
241         /** The collaborator. */
242         GenericClass<N> collaborator;
243 
244         /** The action. */
245         Callable<C> action;
246     }
247 
248     /** The tested 2. */
249     @Tested
250     SUTWithBoundedTypeParameter<Integer, String> tested2;
251 
252     /** The tested 3. */
253     @Tested
254     SUTWithBoundedTypeParameter<Number, CharSequence> tested3;
255 
256     /** The tested 4. */
257     @Tested
258     SUTWithBoundedTypeParameter<?, ?> tested4;
259 
260     /** The tested 5. */
261     @Tested
262     SUTWithBoundedTypeParameter<Long, StringBuilder> tested5;
263 
264     /**
265      * Use SUT declared with type bound.
266      *
267      * @param name
268      *            the name
269      * @param textAction
270      *            the text action
271      * @param collaborator
272      *            the collaborator
273      */
274     @Test
275     void useSUTDeclaredWithTypeBound(@Injectable("test") String name, @Injectable Callable<String> textAction,
276             @Injectable GenericClass<? extends Number> collaborator) {
277         assertSame(numberToInject, tested2.numberValue);
278         assertSame(name, tested2.textValue);
279         assertSame(collaborator, tested2.collaborator);
280         assertSame(textAction, tested2.action);
281 
282         assertSame(numberToInject, tested3.numberValue);
283         assertSame(name, tested3.textValue);
284         assertSame(collaborator, tested3.collaborator);
285         assertSame(textAction, tested3.action);
286 
287         assertSame(numberToInject, tested4.numberValue);
288         assertSame(name, tested4.textValue);
289         assertSame(collaborator, tested4.collaborator);
290         assertSame(textAction, tested4.action);
291 
292         assertNull(tested5.numberValue);
293         assertNull(tested5.textValue);
294         assertSame(collaborator, tested5.collaborator);
295         assertNull(tested5.action);
296     }
297 
298     /**
299      * Use SUT declared with type bound having non matching injectable with wildcard.
300      *
301      * @param action
302      *            the action
303      */
304     @Test
305     void useSUTDeclaredWithTypeBoundHavingNonMatchingInjectableWithWildcard(
306             @Injectable Callable<? extends Number> action) {
307         assertNull(tested2.action);
308         assertNull(tested3.action);
309         assertNull(tested4.action);
310         assertNull(tested5.action);
311     }
312 
313     /**
314      * The Class Base.
315      *
316      * @param <B>
317      *            the generic type
318      */
319     static class Base<B> {
320         /** The dep. */
321         B dep;
322     }
323 
324     /**
325      * The Class Derived.
326      *
327      * @param <D>
328      *            the generic type
329      */
330     static class Derived<D> extends Base<D> {
331     }
332 
333     /**
334      * The Class Concrete.
335      */
336     static final class Concrete extends Derived<Dep> {
337     }
338 
339     /**
340      * The Interface Dep.
341      */
342     public interface Dep {
343     }
344 
345     /** The dep. */
346     @Injectable
347     final Dep dep = new Dep() {
348     };
349 
350     /** The sut. */
351     @Tested
352     Concrete sut;
353 
354     /**
355      * Use SUT class extending generic base class which extends another generic base class containing A generic
356      * dependency.
357      */
358     @Test
359     void useSUTClassExtendingGenericBaseClassWhichExtendsAnotherGenericBaseClassContainingAGenericDependency() {
360         assertSame(dep, sut.dep);
361     }
362 
363     /**
364      * The Class AnotherDep.
365      */
366     public static class AnotherDep {
367     }
368 
369     /**
370      * The Class Concrete2.
371      */
372     static class Concrete2 extends Base<AnotherDep> {
373     }
374 
375     /** The sut 2. */
376     @Tested(fullyInitialized = true)
377     Concrete2 sut2;
378 
379     /**
380      * Use fully initialized SUT class extending generic base class.
381      */
382     @Test
383     void useFullyInitializedSUTClassExtendingGenericBaseClass() {
384         AnotherDep anotherDep = sut2.dep;
385         assertNotNull(anotherDep);
386     }
387 
388     /**
389      * The Class Concrete3.
390      */
391     static class Concrete3 extends Derived<AnotherDep> {
392     }
393 
394     /** The sut 3. */
395     @Tested(fullyInitialized = true)
396     Concrete3 sut3;
397 
398     /**
399      * Use fully initialized SUT class extending generic class which extends another generic class.
400      */
401     @Test
402     void useFullyInitializedSUTClassExtendingGenericClassWhichExtendsAnotherGenericClass() {
403         AnotherDep anotherDep = sut3.dep;
404         assertNotNull(anotherDep);
405     }
406 
407     /**
408      * The Class TestedClassWithConstructorParameterOfGenericType.
409      */
410     static class TestedClassWithConstructorParameterOfGenericType {
411 
412         /** The a class. */
413         private final Class<?> aClass;
414 
415         /**
416          * Instantiates a new tested class with constructor parameter of generic type.
417          *
418          * @param aClass
419          *            the a class
420          */
421         TestedClassWithConstructorParameterOfGenericType(Class<?> aClass) {
422             this.aClass = aClass;
423         }
424     }
425 
426     /** The a class. */
427     @Tested
428     final Class<?> aClass = Long.class;
429 
430     /** The tested 6. */
431     @Tested(fullyInitialized = true)
432     TestedClassWithConstructorParameterOfGenericType tested6;
433 
434     /**
435      * Verify instantiation of class with constructor parameter of generic type.
436      */
437     @Test
438     void verifyInstantiationOfClassWithConstructorParameterOfGenericType() {
439         assertSame(aClass, tested6.aClass);
440     }
441 
442     /**
443      * The Class GenericClassWithDependencyUsingTypeParameter.
444      *
445      * @param <T>
446      *            the generic type
447      */
448     static class GenericClassWithDependencyUsingTypeParameter<T> {
449         /** The dependency. */
450         GenericClass<T> dependency;
451     }
452 
453     /** The dependency. */
454     @Tested
455     final GenericClass<String> dependency = new GenericClass<>();
456 
457     /** The tested 7. */
458     @Tested(fullyInitialized = true)
459     GenericClassWithDependencyUsingTypeParameter<String> tested7;
460 
461     /**
462      * Verify instantiation of generic class with dependency using type parameter.
463      */
464     @Test
465     void verifyInstantiationOfGenericClassWithDependencyUsingTypeParameter() {
466         assertSame(dependency, tested7.dependency);
467     }
468 
469     /**
470      * The Interface Interface.
471      */
472     public interface Interface {
473     }
474 
475     /**
476      * The Class Implementation.
477      */
478     static class Implementation implements Interface {
479     }
480 
481     /**
482      * The Class Derived2.
483      */
484     static class Derived2 extends Base<Interface> {
485     }
486 
487     /** The impl. */
488     @Tested
489     Implementation impl;
490 
491     /** The tested. */
492     @Tested(fullyInitialized = true)
493     Derived2 tested;
494 
495     /**
496      * Use tested object of implementation type for type variable in generic base class.
497      */
498     @Test
499     void useTestedObjectOfImplementationTypeForTypeVariableInGenericBaseClass() {
500         assertSame(impl, tested.dep);
501     }
502 
503     /**
504      * The Class ClassWithFieldOfGenericTypeContainingGenericArray.
505      */
506     static class ClassWithFieldOfGenericTypeContainingGenericArray {
507         /** The n. */
508         @SuppressWarnings("unused")
509         int n;
510         /** The list. */
511         List<Comparable<?>[]> list;
512     }
513 
514     /**
515      * Instantiate object containing generic type field with generic array element.
516      *
517      * @param t
518      *            the t
519      */
520     @Test
521     void instantiateObjectContainingGenericTypeFieldWithGenericArrayElement(
522             @Tested ClassWithFieldOfGenericTypeContainingGenericArray t) {
523         assertNotNull(t);
524     }
525 }