1
2
3
4
5
6 package otherTests;
7
8 import static org.junit.jupiter.api.Assertions.assertEquals;
9 import static org.junit.jupiter.api.Assertions.assertNotNull;
10 import static org.junit.jupiter.api.Assertions.assertSame;
11 import static org.junit.jupiter.api.Assertions.assertThrows;
12
13 import java.security.SecureRandom;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.HashSet;
17 import java.util.List;
18 import java.util.Set;
19
20 import mockit.Deencapsulation;
21
22 import org.junit.jupiter.api.Test;
23
24 final class DeencapsulationTest {
25
26 static final class Subclass extends BaseClass {
27 private static final SecureRandom SECURE_RANDOM = new SecureRandom();
28 final int INITIAL_VALUE = SECURE_RANDOM.nextInt();
29 final int initialValue = -1;
30
31 @SuppressWarnings("unused")
32 private static final Integer constantField = 123;
33
34 private static StringBuilder buffer;
35 @SuppressWarnings("unused")
36 private static char static1;
37 @SuppressWarnings("unused")
38 private static char static2;
39
40 static StringBuilder getBuffer() {
41 return buffer;
42 }
43
44 static void setBuffer(StringBuilder buffer) {
45 Subclass.buffer = buffer;
46 }
47
48 private String stringField;
49 private int intField;
50 private int intField2;
51 private List<String> listField;
52
53 @SuppressWarnings("unused")
54 private String privateMethod(int value) {
55 return "result-" + value;
56 }
57
58 @SuppressWarnings("unused")
59 private static String privateStaticMethod(String arg) {
60 return "static-" + arg;
61 }
62
63 int getIntField() {
64 return intField;
65 }
66
67 void setIntField(int intField) {
68 this.intField = intField;
69 }
70
71 int getIntField2() {
72 return intField2;
73 }
74
75 void setIntField2(int intField2) {
76 this.intField2 = intField2;
77 }
78
79 String getStringField() {
80 return stringField;
81 }
82
83 void setStringField(String stringField) {
84 this.stringField = stringField;
85 }
86
87 List<String> getListField() {
88 return listField;
89 }
90
91 void setListField(List<String> listField) {
92 this.listField = listField;
93 }
94 }
95
96 final Subclass anInstance = new Subclass();
97
98 @Test
99 void getInstanceFieldByName() {
100 anInstance.setIntField(3);
101 anInstance.setStringField("test");
102 anInstance.setListField(Collections.<String> emptyList());
103
104 Integer intValue = Deencapsulation.getField(anInstance, "intField");
105 String stringValue = Deencapsulation.getField(anInstance, "stringField");
106 List<String> listValue = Deencapsulation.getField(anInstance, "listField");
107
108 assertEquals(anInstance.getIntField(), intValue.intValue());
109 assertEquals(anInstance.getStringField(), stringValue);
110 assertSame(anInstance.getListField(), listValue);
111 }
112
113 @Test
114 public void attemptToGetInstanceFieldByNameWithWrongName() {
115 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
116 Deencapsulation.getField(anInstance, "noField");
117 });
118 assertEquals("No instance field of name \"noField\" found in class otherTests.BaseClass",
119 throwable.getMessage());
120 }
121
122 @Test
123 void getInheritedInstanceFieldByName() {
124 anInstance.baseInt = 3;
125 anInstance.baseString = "test";
126 anInstance.baseSet = Collections.emptySet();
127
128 Integer intValue = Deencapsulation.getField(anInstance, "baseInt");
129 String stringValue = Deencapsulation.getField(anInstance, "baseString");
130 Set<Boolean> listValue = Deencapsulation.getField(anInstance, "baseSet");
131
132 assertEquals(anInstance.baseInt, intValue.intValue());
133 assertEquals(anInstance.baseString, stringValue);
134 assertSame(anInstance.baseSet, listValue);
135 }
136
137 @Test
138 @SuppressWarnings("unchecked")
139 void getInstanceFieldByType() {
140 anInstance.setStringField("by type");
141 anInstance.setListField(new ArrayList<String>());
142
143 String stringValue = Deencapsulation.getField(anInstance, String.class);
144 List<String> listValue = Deencapsulation.getField(anInstance, List.class);
145 List<String> listValue2 = Deencapsulation.getField(anInstance, ArrayList.class);
146
147 assertEquals(anInstance.getStringField(), stringValue);
148 assertSame(anInstance.getListField(), listValue);
149 assertSame(listValue, listValue2);
150 }
151
152 @Test
153 public void attemptToGetInstanceFieldByTypeWithWrongType() {
154 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
155 Deencapsulation.getField(anInstance, Byte.class);
156 });
157 assertEquals("Instance field of type byte or Byte not found in class otherTests.BaseClass",
158 throwable.getMessage());
159 }
160
161 @Test
162 public void attemptToGetInstanceFieldByTypeForClassWithMultipleFieldsOfThatType() {
163 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
164 Deencapsulation.getField(anInstance, int.class);
165 });
166 assertEquals("More than one instance field from which a value of type int "
167 + "can be read exists in class otherTests.DeencapsulationTest$Subclass: "
168 + "INITIAL_VALUE, initialValue", throwable.getMessage());
169 }
170
171 @Test
172 @SuppressWarnings("unchecked")
173 void getInheritedInstanceFieldByType() {
174 Set<Boolean> fieldValueOnInstance = new HashSet<>();
175 anInstance.baseSet = fieldValueOnInstance;
176
177 Set<Boolean> setValue = Deencapsulation.getField(anInstance, fieldValueOnInstance.getClass());
178 Set<Boolean> setValue2 = Deencapsulation.getField(anInstance, HashSet.class);
179
180 assertSame(fieldValueOnInstance, setValue);
181 assertSame(setValue, setValue2);
182 }
183
184 @Test
185 void getInstanceFieldOnBaseClassByType() {
186 anInstance.setLongField(15);
187
188 long longValue = Deencapsulation.getField(anInstance, long.class);
189
190 assertEquals(15, longValue);
191 }
192
193 @Test
194 void getStaticFieldByName() {
195 Subclass.setBuffer(new StringBuilder());
196
197 StringBuilder b = Deencapsulation.getField(Subclass.class, "buffer");
198
199 assertSame(Subclass.getBuffer(), b);
200 }
201
202 @Test
203 public void attemptToGetStaticFieldByNameFromWrongClass() {
204 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
205 Deencapsulation.getField(BaseClass.class, "buffer");
206 });
207 assertEquals("No static field of name \"buffer\" found in class otherTests.BaseClass", throwable.getMessage());
208 }
209
210 @Test
211 void getStaticFieldByType() {
212 Subclass.setBuffer(new StringBuilder());
213
214 StringBuilder b = Deencapsulation.getField(Subclass.class, StringBuilder.class);
215
216 assertSame(Subclass.getBuffer(), b);
217 }
218
219 @Test
220 void setInstanceFieldByName() {
221 anInstance.setIntField2(1);
222
223 Deencapsulation.setField(anInstance, "intField2", 901);
224
225 assertEquals(901, anInstance.getIntField2());
226 }
227
228 @Test
229 public void attemptToSetInstanceFieldByNameWithWrongName() {
230 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
231 Deencapsulation.setField(anInstance, "noField", 901);
232 });
233 assertEquals("No instance field of name \"noField\" found in class otherTests.BaseClass",
234 throwable.getMessage());
235 }
236
237 @Test
238 void setInstanceFieldByType() {
239 anInstance.setStringField("");
240
241 Deencapsulation.setField(anInstance, "Test");
242
243 assertEquals("Test", anInstance.getStringField());
244 }
245
246 @Test
247 public void attemptToSetInstanceFieldByTypeWithWrongType() {
248 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
249 Deencapsulation.setField(anInstance, (byte) 123);
250 });
251 assertEquals("Instance field of type byte or Byte not found in class otherTests.BaseClass",
252 throwable.getMessage());
253 }
254
255 @Test
256 public void attemptToSetInstanceFieldByTypeForClassWithMultipleFieldsOfThatType() {
257 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
258 Deencapsulation.setField(anInstance, 901);
259 });
260 assertEquals(
261 "More than one instance field to which a value of type int "
262 + "or Integer can be assigned exists in class "
263 + "otherTests.DeencapsulationTest$Subclass: INITIAL_VALUE, initialValue",
264 throwable.getMessage());
265 }
266
267 @Test
268 void setStaticFieldByName() {
269 Subclass.setBuffer(null);
270
271 Deencapsulation.setField(Subclass.class, "buffer", new StringBuilder());
272
273 assertNotNull(Subclass.getBuffer());
274 }
275
276 @Test
277 public void attemptToSetStaticFieldByNameWithWrongName() {
278 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
279 Deencapsulation.setField(Subclass.class, "noField", null);
280 });
281 assertEquals("No static field of name \"noField\" found in class otherTests.BaseClass", throwable.getMessage());
282 }
283
284 @Test
285 void setStaticFieldByType() {
286 Subclass.setBuffer(null);
287
288 Deencapsulation.setField(Subclass.class, new StringBuilder());
289
290 assertNotNull(Subclass.getBuffer());
291 }
292
293 @Test
294 public void attemptToSetFieldByTypeWithoutAValue() {
295 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
296 Deencapsulation.setField(Subclass.class, null);
297 });
298 assertEquals("Missing field value when setting field by type", throwable.getMessage());
299 }
300
301 @Test
302 public void attemptToSetStaticFieldByTypeWithWrongType() {
303 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
304 Deencapsulation.setField(Subclass.class, new String());
305 });
306 assertEquals("Static field of type String not found in class otherTests.BaseClass", throwable.getMessage());
307 }
308
309 @Test
310 public void attemptToSetStaticFieldByTypeForClassWithMultipleFieldsOfThatType() {
311 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
312 Deencapsulation.setField(Subclass.class, 'A');
313 });
314 assertEquals("More than one static field to which a value of type char or "
315 + "Character can be assigned exists in class "
316 + "otherTests.DeencapsulationTest$Subclass: static1, static2", throwable.getMessage());
317 }
318
319 @Test
320 void setFinalInstanceFields() {
321 Subclass obj = new Subclass();
322
323 Deencapsulation.setField(obj, "INITIAL_VALUE", 123);
324 Deencapsulation.setField(obj, "initialValue", 123);
325
326 assertEquals(123, obj.INITIAL_VALUE);
327 assertEquals(123, (int) Deencapsulation.getField(obj, "initialValue"));
328 assertEquals(-1, obj.initialValue);
329 }
330
331 @Test
332 public void attemptToSetAStaticFinalField() {
333 Throwable throwable = assertThrows(RuntimeException.class, () -> {
334 Deencapsulation.setField(Subclass.class, "constantField", 54);
335 });
336 assertEquals(
337 "java.lang.IllegalAccessException: Can not set static final java.lang.Integer "
338 + "field otherTests.DeencapsulationTest$Subclass.constantField to java.lang.Integer",
339 throwable.getMessage());
340 }
341
342 @Test
343 void invokeInstanceMethodWithExplicitParameterTypes() {
344 String result = Deencapsulation.invoke(anInstance, "privateMethod", new Class<?>[] { int.class }, 42);
345
346 assertEquals("result-42", result);
347 }
348
349 @Test
350 void invokeInstanceMethodWithNonNullArgs() {
351 String result = Deencapsulation.invoke(anInstance, "privateMethod", 7);
352
353 assertEquals("result-7", result);
354 }
355
356 @Test
357 void invokeStaticMethodWithExplicitParameterTypes() {
358 String result = Deencapsulation.invoke(Subclass.class, "privateStaticMethod", new Class<?>[] { String.class },
359 "hello");
360
361 assertEquals("static-hello", result);
362 }
363
364 @Test
365 void invokeStaticMethodWithNonNullArgs() {
366 String result = Deencapsulation.invoke(Subclass.class, "privateStaticMethod", "world");
367
368 assertEquals("static-world", result);
369 }
370
371 @Test
372 void invokeStaticMethodByClassName() {
373 String result = Deencapsulation.invoke("otherTests.DeencapsulationTest$Subclass", "privateStaticMethod",
374 "byName");
375
376 assertEquals("static-byName", result);
377 }
378 }