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