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 mockit.integration.junit5.JMockitExtension;
17
18 import org.junit.jupiter.api.Test;
19 import org.junit.jupiter.api.extension.ExtendWith;
20
21 @ExtendWith(JMockitExtension.class)
22 class MockUpForGenericsTest {
23
24
25 public static final class Collaborator {
26 public <N extends Number> N genericMethod(@SuppressWarnings("UnusedParameters") N n) {
27 return null;
28 }
29 }
30
31 @Test
32 void mockGenericMethod() {
33 new MockUp<Collaborator>() {
34 @Mock
35 <T extends Number> T genericMethod(T t) {
36 return t;
37 }
38
39
40
41 };
42
43 Integer n = new Collaborator().genericMethod(123);
44 assertEquals(123, n.intValue());
45
46 Long l = new Collaborator().genericMethod(45L);
47 assertEquals(45L, l.longValue());
48
49 Short s = new Collaborator().genericMethod((short) 6);
50 assertEquals(6, s.shortValue());
51
52 Double d = new Collaborator().genericMethod(0.5);
53 assertEquals(0.5, d, 0);
54 }
55
56 @SuppressWarnings("UnusedParameters")
57 public static final class GenericClass<T1, T2> {
58 public void aMethod(T1 t) {
59 throw new RuntimeException("t=" + t);
60 }
61
62 public int anotherMethod(T1 t, int i, T2 p) {
63 return 2 * i;
64 }
65
66 public int anotherMethod(Integer t, int i, String p) {
67 return -2 * i;
68 }
69 }
70
71 @Test
72 void mockGenericClassWithUnspecifiedTypeArguments() {
73 new MockUp<GenericClass<?, ?>>() {
74 @Mock
75 void aMethod(Object o) {
76 StringBuilder s = (StringBuilder) o;
77 s.setLength(0);
78 s.append("mock");
79 s.toString();
80 }
81
82 @Mock
83 int anotherMethod(Object o, int i, Object list) {
84 assertTrue(o instanceof StringBuilder);
85
86 assertEquals(0, ((Collection<String>) list).size());
87 return -i;
88 }
89 };
90
91 StringBuilder s = new StringBuilder("test");
92 GenericClass<StringBuilder, List<String>> g = new GenericClass<>();
93
94 g.aMethod(s);
95 int r1 = g.anotherMethod(new StringBuilder("test"), 58, Collections.<String> emptyList());
96 int r2 = g.anotherMethod(123, 65, "abc");
97
98 assertEquals("mock", s.toString());
99 assertEquals(-58, r1);
100 assertEquals(-130, r2);
101 }
102
103 @Test
104 void mockBothGenericAndNonGenericMethodsInGenericClass() {
105 new MockUp<GenericClass<String, Boolean>>() {
106 @Mock
107 int anotherMethod(Integer t, int i, String p) {
108 return 2;
109 }
110
111 @Mock
112 int anotherMethod(String t, int i, Boolean p) {
113 return 1;
114 }
115 };
116
117 GenericClass<String, Boolean> o = new GenericClass<>();
118 assertEquals(1, o.anotherMethod("generic", 1, true));
119 assertEquals(2, o.anotherMethod(123, 2, "non generic"));
120 }
121
122 static class GenericBaseClass<T, U> {
123 public U find(@SuppressWarnings("UnusedParameters") T id) {
124 return null;
125 }
126 }
127
128 @Test
129 void mockGenericMethodWithMockMethodHavingParameterTypesMatchingTypeArguments() {
130 new MockUp<GenericBaseClass<String, Integer>>() {
131 @Mock
132 Integer find(String id) {
133 return id.hashCode();
134 }
135 };
136
137 int i = new GenericBaseClass<String, Integer>().find("test");
138 assertEquals("test".hashCode(), i);
139 }
140
141 @Test
142 void cannotCallGenericMethodWhenSomeMockMethodExpectsDifferentTypes() {
143 new MockUp<GenericBaseClass<String, Integer>>() {
144 @Mock
145 Integer find(String id) {
146 return 1;
147 }
148 };
149
150 try {
151 new GenericBaseClass<Integer, String>().find(1);
152 fail();
153 } catch (IllegalArgumentException e) {
154 assertTrue(e.getMessage().startsWith("Failure to invoke method: "));
155 }
156 }
157
158 static class NonGenericSuperclass extends GenericBaseClass<Integer, String> {
159 }
160
161 final class NonGenericSubclass extends NonGenericSuperclass {
162 }
163
164 @Test
165 void mockGenericMethodFromInstantiationOfNonGenericSubclass() {
166 new MockUp<NonGenericSubclass>() {
167 @Mock
168 String find(Integer id) {
169 return "mocked" + id;
170 }
171 };
172
173 String s = new NonGenericSubclass().find(1);
174 assertEquals("mocked1", s);
175 }
176
177 static class GenericSuperclass<I> extends GenericBaseClass<I, String> {
178 }
179
180 final class AnotherNonGenericSubclass extends GenericSuperclass<Integer> {
181 }
182
183 @Test
184 void mockGenericMethodFromInstantiationOfNonGenericSubclassWhichExtendsAGenericIntermediateSuperclass() {
185 new MockUp<AnotherNonGenericSubclass>() {
186 @Mock
187 String find(Integer id) {
188 return "mocked" + id;
189 }
190 };
191
192 String s = new AnotherNonGenericSubclass().find(1);
193 assertEquals("mocked1", s);
194 }
195
196 @SuppressWarnings("UnusedParameters")
197 public static class NonGenericClassWithGenericMethods {
198 public static <T> T staticMethod(Class<T> cls, String s) {
199 throw new RuntimeException();
200 }
201
202 public <C> void instanceMethod(Class<C> cls, String s) {
203 throw new RuntimeException();
204 }
205
206 public final <N extends Number> void instanceMethod(Class<N> cls) {
207 throw new RuntimeException();
208 }
209 }
210
211 @Test
212 void mockGenericMethodsOfNonGenericClass() {
213 new MockUp<NonGenericClassWithGenericMethods>() {
214 @Mock
215 <T> T staticMethod(Class<T> cls, String s) {
216 return null;
217 }
218
219 @Mock
220 <C> void instanceMethod(Class<C> cls, String s) {
221 }
222
223 @Mock
224 void instanceMethod(Class<?> cls) {
225 }
226 };
227
228 new NonGenericClassWithGenericMethods().instanceMethod(Integer.class);
229 NonGenericClassWithGenericMethods.staticMethod(Collaborator.class, "test1");
230 new NonGenericClassWithGenericMethods().instanceMethod(Byte.class, "test2");
231 }
232
233
234
235 public interface GenericInterface<T> {
236 void method(T t);
237 }
238
239 @Test
240 void mockGenericInterfaceMethodWithMockMethodHavingParameterOfTypeObject() {
241 GenericInterface<Boolean> mock = new MockUp<GenericInterface<Boolean>>() {
242 @Mock
243 void method(Object b) {
244 assertTrue((Boolean) b);
245 }
246 }.getMockInstance();
247
248 mock.method(true);
249 }
250
251 public interface NonGenericSubInterface extends GenericInterface<Long> {
252 }
253
254 @Test
255 void mockMethodOfSubInterfaceWithGenericTypeArgument() {
256 NonGenericSubInterface mock = new MockUp<NonGenericSubInterface>() {
257 @Mock
258 void method(Long l) {
259 assertTrue(l > 0);
260 }
261 }.getMockInstance();
262
263 mock.method(123L);
264 }
265
266 @Test
267 void mockGenericInterfaceMethod() {
268 Comparable<Integer> cmp = new MockUp<Comparable<Integer>>() {
269 @Mock
270 int compareTo(Integer i) {
271 assertEquals(123, i.intValue());
272 return 2;
273 }
274 }.getMockInstance();
275
276 assertEquals(2, cmp.compareTo(123));
277 }
278 }