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