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
17
18 final class TestedClassWithGenericsTest {
19
20
21
22
23
24
25
26 public interface Collaborator<T> {
27
28
29
30
31
32 T getValue();
33 }
34
35
36
37
38
39
40
41 static class SUTWithUnboundedTypeParameter<T> {
42
43
44 T value;
45
46
47 final Collaborator<T> collaborator;
48
49
50 final Iterable<Collaborator<T>> collaborators;
51
52 Map<T, ?> values;
53
54
55 Callable<T> action1;
56
57
58 Callable<?> action2;
59
60
61
62
63
64
65
66 @SuppressWarnings("unused")
67 SUTWithUnboundedTypeParameter(Collaborator<T> c) {
68 collaborator = c;
69 collaborators = null;
70 }
71
72
73
74
75
76
77
78
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
96 @Tested
97 SUTWithUnboundedTypeParameter<Integer> tested1;
98
99
100 @Injectable
101 final Integer numberToInject = 123;
102
103
104 @Injectable
105 Collaborator<Integer> mockCollaborator;
106
107
108
109
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
123
124
125
126
127
128
129
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
145
146
147
148
149
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
164
165
166
167
168 static class SUTWithGenericConstructor<T> {
169
170
171 final Map<T, ?> values;
172
173
174
175
176
177
178
179
180
181 @SuppressWarnings("unused")
182 <V extends CharSequence & Serializable> SUTWithGenericConstructor(Map<T, V> values) {
183 this.values = values;
184 }
185 }
186
187
188 @Tested
189 final Map<Integer, String> mapValues = new HashMap<>();
190
191
192 @Tested
193 SUTWithGenericConstructor<Integer> tested8;
194
195
196
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
216
217
218
219
220 static class GenericClass<T> {
221
222 T value;
223 }
224
225
226
227
228
229
230
231
232
233 static class SUTWithBoundedTypeParameter<N extends Number, C extends CharSequence> {
234
235
236 C textValue;
237
238
239 N numberValue;
240
241
242 GenericClass<N> collaborator;
243
244
245 Callable<C> action;
246 }
247
248
249 @Tested
250 SUTWithBoundedTypeParameter<Integer, String> tested2;
251
252
253 @Tested
254 SUTWithBoundedTypeParameter<Number, CharSequence> tested3;
255
256
257 @Tested
258 SUTWithBoundedTypeParameter<?, ?> tested4;
259
260
261 @Tested
262 SUTWithBoundedTypeParameter<Long, StringBuilder> tested5;
263
264
265
266
267
268
269
270
271
272
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
300
301
302
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
315
316
317
318
319 static class Base<B> {
320
321 B dep;
322 }
323
324
325
326
327
328
329
330 static class Derived<D> extends Base<D> {
331 }
332
333
334
335
336 static final class Concrete extends Derived<Dep> {
337 }
338
339
340
341
342 public interface Dep {
343 }
344
345
346 @Injectable
347 final Dep dep = new Dep() {
348 };
349
350
351 @Tested
352 Concrete sut;
353
354
355
356
357
358 @Test
359 void useSUTClassExtendingGenericBaseClassWhichExtendsAnotherGenericBaseClassContainingAGenericDependency() {
360 assertSame(dep, sut.dep);
361 }
362
363
364
365
366 public static class AnotherDep {
367 }
368
369
370
371
372 static class Concrete2 extends Base<AnotherDep> {
373 }
374
375
376 @Tested(fullyInitialized = true)
377 Concrete2 sut2;
378
379
380
381
382 @Test
383 void useFullyInitializedSUTClassExtendingGenericBaseClass() {
384 AnotherDep anotherDep = sut2.dep;
385 assertNotNull(anotherDep);
386 }
387
388
389
390
391 static class Concrete3 extends Derived<AnotherDep> {
392 }
393
394
395 @Tested(fullyInitialized = true)
396 Concrete3 sut3;
397
398
399
400
401 @Test
402 void useFullyInitializedSUTClassExtendingGenericClassWhichExtendsAnotherGenericClass() {
403 AnotherDep anotherDep = sut3.dep;
404 assertNotNull(anotherDep);
405 }
406
407
408
409
410 static class TestedClassWithConstructorParameterOfGenericType {
411
412
413 private final Class<?> aClass;
414
415
416
417
418
419
420
421 TestedClassWithConstructorParameterOfGenericType(Class<?> aClass) {
422 this.aClass = aClass;
423 }
424 }
425
426
427 @Tested
428 final Class<?> aClass = Long.class;
429
430
431 @Tested(fullyInitialized = true)
432 TestedClassWithConstructorParameterOfGenericType tested6;
433
434
435
436
437 @Test
438 void verifyInstantiationOfClassWithConstructorParameterOfGenericType() {
439 assertSame(aClass, tested6.aClass);
440 }
441
442
443
444
445
446
447
448 static class GenericClassWithDependencyUsingTypeParameter<T> {
449
450 GenericClass<T> dependency;
451 }
452
453
454 @Tested
455 final GenericClass<String> dependency = new GenericClass<>();
456
457
458 @Tested(fullyInitialized = true)
459 GenericClassWithDependencyUsingTypeParameter<String> tested7;
460
461
462
463
464 @Test
465 void verifyInstantiationOfGenericClassWithDependencyUsingTypeParameter() {
466 assertSame(dependency, tested7.dependency);
467 }
468
469
470
471
472 public interface Interface {
473 }
474
475
476
477
478 static class Implementation implements Interface {
479 }
480
481
482
483
484 static class Derived2 extends Base<Interface> {
485 }
486
487
488 @Tested
489 Implementation impl;
490
491
492 @Tested(fullyInitialized = true)
493 Derived2 tested;
494
495
496
497
498 @Test
499 void useTestedObjectOfImplementationTypeForTypeVariableInGenericBaseClass() {
500 assertSame(impl, tested.dep);
501 }
502
503
504
505
506 static class ClassWithFieldOfGenericTypeContainingGenericArray {
507
508 @SuppressWarnings("unused")
509 int n;
510
511 List<Comparable<?>[]> list;
512 }
513
514
515
516
517
518
519
520 @Test
521 void instantiateObjectContainingGenericTypeFieldWithGenericArrayElement(
522 @Tested ClassWithFieldOfGenericTypeContainingGenericArray t) {
523 assertNotNull(t);
524 }
525 }