1
2
3
4
5
6 package mockit;
7
8 import static org.junit.jupiter.api.Assertions.assertEquals;
9 import static org.junit.jupiter.api.Assertions.assertTrue;
10 import static org.junit.jupiter.api.Assertions.fail;
11
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.List;
15
16 import org.junit.jupiter.api.Test;
17
18
19
20
21 final class FakeForGenericsTest {
22
23
24
25
26 public static final class Collaborator {
27
28
29
30
31
32
33
34
35
36
37
38 public <N extends Number> N genericMethod(@SuppressWarnings("UnusedParameters") N n) {
39 return null;
40 }
41 }
42
43
44
45
46 @Test
47 void fakeGenericMethod() {
48 new MockUp<Collaborator>() {
49 @Mock
50 <T extends Number> T genericMethod(T t) {
51 return t;
52 }
53
54
55
56 };
57
58 Integer n = new Collaborator().genericMethod(123);
59 assertEquals(123, n.intValue());
60
61 Long l = new Collaborator().genericMethod(45L);
62 assertEquals(45L, l.longValue());
63
64 Short s = new Collaborator().genericMethod((short) 6);
65 assertEquals(6, s.shortValue());
66
67 Double d = new Collaborator().genericMethod(0.5);
68 assertEquals(0.5, d, 0);
69 }
70
71
72
73
74
75
76
77
78
79 @SuppressWarnings("UnusedParameters")
80 public static final class GenericClass<T1, T2> {
81
82
83
84
85
86
87
88 public void aMethod(T1 t) {
89 throw new RuntimeException("t=" + t);
90 }
91
92
93
94
95
96
97
98
99
100
101
102
103
104 public int anotherMethod(T1 t, int i, T2 p) {
105 return 2 * i;
106 }
107
108
109
110
111
112
113
114
115
116
117
118
119
120 public int anotherMethod(Integer t, int i, String p) {
121 return -2 * i;
122 }
123 }
124
125
126
127
128 @Test
129 void fakeGenericClassWithUnspecifiedTypeArguments() {
130 new MockUp<GenericClass<?, ?>>() {
131 @Mock
132 void aMethod(Object o) {
133 StringBuilder s = (StringBuilder) o;
134 s.setLength(0);
135 s.append("fake");
136 s.toString();
137 }
138
139 @Mock
140 int anotherMethod(Object o, int i, Object list) {
141 assertTrue(o instanceof StringBuilder);
142
143 assertEquals(0, ((Collection<String>) list).size());
144 return -i;
145 }
146 };
147
148 StringBuilder s = new StringBuilder("test");
149 GenericClass<StringBuilder, List<String>> g = new GenericClass<>();
150
151 g.aMethod(s);
152 int r1 = g.anotherMethod(new StringBuilder("test"), 58, Collections.<String> emptyList());
153 int r2 = g.anotherMethod(123, 65, "abc");
154
155 assertEquals("fake", s.toString());
156 assertEquals(-58, r1);
157 assertEquals(-130, r2);
158 }
159
160
161
162
163 @Test
164 void fakeBothGenericAndNonGenericMethodsInGenericClass() {
165 new MockUp<GenericClass<String, Boolean>>() {
166 @Mock
167 int anotherMethod(Integer t, int i, String p) {
168 return 2;
169 }
170
171 @Mock
172 int anotherMethod(String t, int i, Boolean p) {
173 return 1;
174 }
175 };
176
177 GenericClass<String, Boolean> o = new GenericClass<>();
178 assertEquals(1, o.anotherMethod("generic", 1, true));
179 assertEquals(2, o.anotherMethod(123, 2, "non generic"));
180 }
181
182
183
184
185
186
187
188
189
190 static class GenericBaseClass<T, U> {
191
192
193
194
195
196
197
198
199 public U find(@SuppressWarnings("UnusedParameters") T id) {
200 return null;
201 }
202 }
203
204
205
206
207 @Test
208 void fakeGenericMethodWithFakeMethodHavingParameterTypesMatchingTypeArguments() {
209 new MockUp<GenericBaseClass<String, Integer>>() {
210 @Mock
211 Integer find(String id) {
212 return id.hashCode();
213 }
214 };
215
216 int i = new GenericBaseClass<String, Integer>().find("test");
217 assertEquals("test".hashCode(), i);
218 }
219
220
221
222
223 @Test
224 void cannotCallGenericMethodWhenSomeFakeMethodExpectsDifferentTypes() {
225 new MockUp<GenericBaseClass<String, Integer>>() {
226 @Mock
227 Integer find(String id) {
228 return 1;
229 }
230 };
231
232 try {
233 new GenericBaseClass<Integer, String>().find(1);
234 fail();
235 } catch (IllegalArgumentException e) {
236 assertTrue(e.getMessage().startsWith("Failure to invoke method: "));
237 }
238 }
239
240
241
242
243 static class NonGenericSuperclass extends GenericBaseClass<Integer, String> {
244 }
245
246
247
248
249 static final class NonGenericSubclass extends NonGenericSuperclass {
250 }
251
252
253
254
255 @Test
256 void fakeGenericMethodFromInstantiationOfNonGenericSubclass() {
257 new MockUp<NonGenericSubclass>() {
258 @Mock
259 String find(Integer id) {
260 return "faked" + id;
261 }
262 };
263
264 String s = new NonGenericSubclass().find(1);
265 assertEquals("faked1", s);
266 }
267
268
269
270
271
272
273
274 static class GenericSuperclass<I> extends GenericBaseClass<I, String> {
275 }
276
277
278
279
280 static final class AnotherNonGenericSubclass extends GenericSuperclass<Integer> {
281 }
282
283
284
285
286 @Test
287 void fakeGenericMethodFromInstantiationOfNonGenericSubclassWhichExtendsAGenericIntermediateSuperclass() {
288 new MockUp<AnotherNonGenericSubclass>() {
289 @Mock
290 String find(Integer id) {
291 return "faked" + id;
292 }
293 };
294
295 String s = new AnotherNonGenericSubclass().find(1);
296 assertEquals("faked1", s);
297 }
298
299
300
301
302 @SuppressWarnings("UnusedParameters")
303 public static class NonGenericClassWithGenericMethods {
304
305
306
307
308
309
310
311
312
313
314
315
316
317 public static <T> T staticMethod(Class<T> cls, String s) {
318 throw new RuntimeException();
319 }
320
321
322
323
324
325
326
327
328
329
330
331 public <C> void instanceMethod(Class<C> cls, String s) {
332 throw new RuntimeException();
333 }
334
335
336
337
338
339
340
341
342
343 public final <N extends Number> void instanceMethod(Class<N> cls) {
344 throw new RuntimeException();
345 }
346 }
347
348
349
350
351 @Test
352 void fakeGenericMethodsOfNonGenericClass() {
353 new MockUp<NonGenericClassWithGenericMethods>() {
354 @Mock
355 <T> T staticMethod(Class<T> cls, String s) {
356 return null;
357 }
358
359 @Mock
360 <C> void instanceMethod(Class<C> cls, String s) {
361 }
362
363 @Mock
364 void instanceMethod(Class<?> cls) {
365 }
366 };
367
368 new NonGenericClassWithGenericMethods().instanceMethod(Integer.class);
369 NonGenericClassWithGenericMethods.staticMethod(Collaborator.class, "test1");
370 new NonGenericClassWithGenericMethods().instanceMethod(Byte.class, "test2");
371 }
372 }