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