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 int getIntField() {
54 return intField;
55 }
56
57 void setIntField(int intField) {
58 this.intField = intField;
59 }
60
61 int getIntField2() {
62 return intField2;
63 }
64
65 void setIntField2(int intField2) {
66 this.intField2 = intField2;
67 }
68
69 String getStringField() {
70 return stringField;
71 }
72
73 void setStringField(String stringField) {
74 this.stringField = stringField;
75 }
76
77 List<String> getListField() {
78 return listField;
79 }
80
81 void setListField(List<String> listField) {
82 this.listField = listField;
83 }
84 }
85
86 final Subclass anInstance = new Subclass();
87
88 @Test
89 void getInstanceFieldByName() {
90 anInstance.setIntField(3);
91 anInstance.setStringField("test");
92 anInstance.setListField(Collections.<String> emptyList());
93
94 Integer intValue = Deencapsulation.getField(anInstance, "intField");
95 String stringValue = Deencapsulation.getField(anInstance, "stringField");
96 List<String> listValue = Deencapsulation.getField(anInstance, "listField");
97
98 assertEquals(anInstance.getIntField(), intValue.intValue());
99 assertEquals(anInstance.getStringField(), stringValue);
100 assertSame(anInstance.getListField(), listValue);
101 }
102
103 @Test
104 public void attemptToGetInstanceFieldByNameWithWrongName() {
105 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
106 Deencapsulation.getField(anInstance, "noField");
107 });
108 assertEquals("No instance field of name \"noField\" found in class otherTests.BaseClass",
109 throwable.getMessage());
110 }
111
112 @Test
113 void getInheritedInstanceFieldByName() {
114 anInstance.baseInt = 3;
115 anInstance.baseString = "test";
116 anInstance.baseSet = Collections.emptySet();
117
118 Integer intValue = Deencapsulation.getField(anInstance, "baseInt");
119 String stringValue = Deencapsulation.getField(anInstance, "baseString");
120 Set<Boolean> listValue = Deencapsulation.getField(anInstance, "baseSet");
121
122 assertEquals(anInstance.baseInt, intValue.intValue());
123 assertEquals(anInstance.baseString, stringValue);
124 assertSame(anInstance.baseSet, listValue);
125 }
126
127 @Test
128 @SuppressWarnings("unchecked")
129 void getInstanceFieldByType() {
130 anInstance.setStringField("by type");
131 anInstance.setListField(new ArrayList<String>());
132
133 String stringValue = Deencapsulation.getField(anInstance, String.class);
134 List<String> listValue = Deencapsulation.getField(anInstance, List.class);
135 List<String> listValue2 = Deencapsulation.getField(anInstance, ArrayList.class);
136
137 assertEquals(anInstance.getStringField(), stringValue);
138 assertSame(anInstance.getListField(), listValue);
139 assertSame(listValue, listValue2);
140 }
141
142 @Test
143 public void attemptToGetInstanceFieldByTypeWithWrongType() {
144 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
145 Deencapsulation.getField(anInstance, Byte.class);
146 });
147 assertEquals("Instance field of type byte or Byte not found in class otherTests.BaseClass",
148 throwable.getMessage());
149 }
150
151 @Test
152 public void attemptToGetInstanceFieldByTypeForClassWithMultipleFieldsOfThatType() {
153 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
154 Deencapsulation.getField(anInstance, int.class);
155 });
156 assertEquals("More than one instance field from which a value of type int "
157 + "can be read exists in class otherTests.DeencapsulationTest$Subclass: "
158 + "INITIAL_VALUE, initialValue", throwable.getMessage());
159 }
160
161 @Test
162 @SuppressWarnings("unchecked")
163 void getInheritedInstanceFieldByType() {
164 Set<Boolean> fieldValueOnInstance = new HashSet<>();
165 anInstance.baseSet = fieldValueOnInstance;
166
167 Set<Boolean> setValue = Deencapsulation.getField(anInstance, fieldValueOnInstance.getClass());
168 Set<Boolean> setValue2 = Deencapsulation.getField(anInstance, HashSet.class);
169
170 assertSame(fieldValueOnInstance, setValue);
171 assertSame(setValue, setValue2);
172 }
173
174 @Test
175 void getInstanceFieldOnBaseClassByType() {
176 anInstance.setLongField(15);
177
178 long longValue = Deencapsulation.getField(anInstance, long.class);
179
180 assertEquals(15, longValue);
181 }
182
183 @Test
184 void getStaticFieldByName() {
185 Subclass.setBuffer(new StringBuilder());
186
187 StringBuilder b = Deencapsulation.getField(Subclass.class, "buffer");
188
189 assertSame(Subclass.getBuffer(), b);
190 }
191
192 @Test
193 public void attemptToGetStaticFieldByNameFromWrongClass() {
194 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
195 Deencapsulation.getField(BaseClass.class, "buffer");
196 });
197 assertEquals("No static field of name \"buffer\" found in class otherTests.BaseClass", throwable.getMessage());
198 }
199
200 @Test
201 void getStaticFieldByType() {
202 Subclass.setBuffer(new StringBuilder());
203
204 StringBuilder b = Deencapsulation.getField(Subclass.class, StringBuilder.class);
205
206 assertSame(Subclass.getBuffer(), b);
207 }
208
209 @Test
210 void setInstanceFieldByName() {
211 anInstance.setIntField2(1);
212
213 Deencapsulation.setField(anInstance, "intField2", 901);
214
215 assertEquals(901, anInstance.getIntField2());
216 }
217
218 @Test
219 public void attemptToSetInstanceFieldByNameWithWrongName() {
220 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
221 Deencapsulation.setField(anInstance, "noField", 901);
222 });
223 assertEquals("No instance field of name \"noField\" found in class otherTests.BaseClass",
224 throwable.getMessage());
225 }
226
227 @Test
228 void setInstanceFieldByType() {
229 anInstance.setStringField("");
230
231 Deencapsulation.setField(anInstance, "Test");
232
233 assertEquals("Test", anInstance.getStringField());
234 }
235
236 @Test
237 public void attemptToSetInstanceFieldByTypeWithWrongType() {
238 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
239 Deencapsulation.setField(anInstance, (byte) 123);
240 });
241 assertEquals("Instance field of type byte or Byte not found in class otherTests.BaseClass",
242 throwable.getMessage());
243 }
244
245 @Test
246 public void attemptToSetInstanceFieldByTypeForClassWithMultipleFieldsOfThatType() {
247 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
248 Deencapsulation.setField(anInstance, 901);
249 });
250 assertEquals(
251 "More than one instance field to which a value of type int "
252 + "or Integer can be assigned exists in class "
253 + "otherTests.DeencapsulationTest$Subclass: INITIAL_VALUE, initialValue",
254 throwable.getMessage());
255 }
256
257 @Test
258 void setStaticFieldByName() {
259 Subclass.setBuffer(null);
260
261 Deencapsulation.setField(Subclass.class, "buffer", new StringBuilder());
262
263 assertNotNull(Subclass.getBuffer());
264 }
265
266 @Test
267 public void attemptToSetStaticFieldByNameWithWrongName() {
268 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
269 Deencapsulation.setField(Subclass.class, "noField", null);
270 });
271 assertEquals("No static field of name \"noField\" found in class otherTests.BaseClass", throwable.getMessage());
272 }
273
274 @Test
275 void setStaticFieldByType() {
276 Subclass.setBuffer(null);
277
278 Deencapsulation.setField(Subclass.class, new StringBuilder());
279
280 assertNotNull(Subclass.getBuffer());
281 }
282
283 @Test
284 public void attemptToSetFieldByTypeWithoutAValue() {
285 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
286 Deencapsulation.setField(Subclass.class, null);
287 });
288 assertEquals("Missing field value when setting field by type", throwable.getMessage());
289 }
290
291 @Test
292 public void attemptToSetStaticFieldByTypeWithWrongType() {
293 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
294 Deencapsulation.setField(Subclass.class, new String());
295 });
296 assertEquals("Static field of type String not found in class otherTests.BaseClass", throwable.getMessage());
297 }
298
299 @Test
300 public void attemptToSetStaticFieldByTypeForClassWithMultipleFieldsOfThatType() {
301 Throwable throwable = assertThrows(IllegalArgumentException.class, () -> {
302 Deencapsulation.setField(Subclass.class, 'A');
303 });
304 assertEquals("More than one static field to which a value of type char or "
305 + "Character can be assigned exists in class "
306 + "otherTests.DeencapsulationTest$Subclass: static1, static2", throwable.getMessage());
307 }
308
309 @Test
310 void setFinalInstanceFields() {
311 Subclass obj = new Subclass();
312
313 Deencapsulation.setField(obj, "INITIAL_VALUE", 123);
314 Deencapsulation.setField(obj, "initialValue", 123);
315
316 assertEquals(123, obj.INITIAL_VALUE);
317 assertEquals(123, (int) Deencapsulation.getField(obj, "initialValue"));
318 assertEquals(-1, obj.initialValue);
319 }
320
321 @Test
322 public void attemptToSetAStaticFinalField() {
323 Throwable throwable = assertThrows(RuntimeException.class, () -> {
324 Deencapsulation.setField(Subclass.class, "constantField", 54);
325 });
326 assertEquals(
327 "java.lang.IllegalAccessException: Can not set static final java.lang.Integer "
328 + "field otherTests.DeencapsulationTest$Subclass.constantField to java.lang.Integer",
329 throwable.getMessage());
330 }
331 }