1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.beans;
18
19 import java.beans.Introspector;
20 import java.beans.PropertyDescriptor;
21 import java.lang.reflect.Method;
22 import java.util.ArrayList;
23 import java.util.List;
24
25 import org.junit.Test;
26
27 import org.springframework.beans.factory.BeanFactory;
28 import org.springframework.beans.propertyeditors.CustomDateEditor;
29 import org.springframework.core.io.Resource;
30 import org.springframework.core.io.ResourceEditor;
31 import org.springframework.tests.sample.beans.DerivedTestBean;
32 import org.springframework.tests.sample.beans.ITestBean;
33 import org.springframework.tests.sample.beans.TestBean;
34
35 import static org.junit.Assert.*;
36
37
38
39
40
41
42
43
44
45 public final class BeanUtilsTests {
46
47 @Test
48 public void testInstantiateClass() {
49
50 BeanUtils.instantiateClass(ArrayList.class);
51
52 try {
53
54 BeanUtils.instantiateClass(List.class);
55 fail("Should have thrown FatalBeanException");
56 }
57 catch (FatalBeanException ex) {
58
59 }
60
61 try {
62
63 BeanUtils.instantiateClass(CustomDateEditor.class);
64 fail("Should have thrown FatalBeanException");
65 }
66 catch (FatalBeanException ex) {
67
68 }
69 }
70
71 @Test
72 public void testGetPropertyDescriptors() throws Exception {
73 PropertyDescriptor[] actual = Introspector.getBeanInfo(TestBean.class).getPropertyDescriptors();
74 PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(TestBean.class);
75 assertNotNull("Descriptors should not be null", descriptors);
76 assertEquals("Invalid number of descriptors returned", actual.length, descriptors.length);
77 }
78
79 @Test
80 public void testBeanPropertyIsArray() {
81 PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(ContainerBean.class);
82 for (PropertyDescriptor descriptor : descriptors) {
83 if ("containedBeans".equals(descriptor.getName())) {
84 assertTrue("Property should be an array", descriptor.getPropertyType().isArray());
85 assertEquals(descriptor.getPropertyType().getComponentType(), ContainedBean.class);
86 }
87 }
88 }
89
90 @Test
91 public void testFindEditorByConvention() {
92 assertEquals(ResourceEditor.class, BeanUtils.findEditorByConvention(Resource.class).getClass());
93 }
94
95 @Test
96 public void testCopyProperties() throws Exception {
97 TestBean tb = new TestBean();
98 tb.setName("rod");
99 tb.setAge(32);
100 tb.setTouchy("touchy");
101 TestBean tb2 = new TestBean();
102 assertTrue("Name empty", tb2.getName() == null);
103 assertTrue("Age empty", tb2.getAge() == 0);
104 assertTrue("Touchy empty", tb2.getTouchy() == null);
105 BeanUtils.copyProperties(tb, tb2);
106 assertTrue("Name copied", tb2.getName().equals(tb.getName()));
107 assertTrue("Age copied", tb2.getAge() == tb.getAge());
108 assertTrue("Touchy copied", tb2.getTouchy().equals(tb.getTouchy()));
109 }
110
111 @Test
112 public void testCopyPropertiesWithDifferentTypes1() throws Exception {
113 DerivedTestBean tb = new DerivedTestBean();
114 tb.setName("rod");
115 tb.setAge(32);
116 tb.setTouchy("touchy");
117 TestBean tb2 = new TestBean();
118 assertTrue("Name empty", tb2.getName() == null);
119 assertTrue("Age empty", tb2.getAge() == 0);
120 assertTrue("Touchy empty", tb2.getTouchy() == null);
121 BeanUtils.copyProperties(tb, tb2);
122 assertTrue("Name copied", tb2.getName().equals(tb.getName()));
123 assertTrue("Age copied", tb2.getAge() == tb.getAge());
124 assertTrue("Touchy copied", tb2.getTouchy().equals(tb.getTouchy()));
125 }
126
127 @Test
128 public void testCopyPropertiesWithDifferentTypes2() throws Exception {
129 TestBean tb = new TestBean();
130 tb.setName("rod");
131 tb.setAge(32);
132 tb.setTouchy("touchy");
133 DerivedTestBean tb2 = new DerivedTestBean();
134 assertTrue("Name empty", tb2.getName() == null);
135 assertTrue("Age empty", tb2.getAge() == 0);
136 assertTrue("Touchy empty", tb2.getTouchy() == null);
137 BeanUtils.copyProperties(tb, tb2);
138 assertTrue("Name copied", tb2.getName().equals(tb.getName()));
139 assertTrue("Age copied", tb2.getAge() == tb.getAge());
140 assertTrue("Touchy copied", tb2.getTouchy().equals(tb.getTouchy()));
141 }
142
143 @Test
144 public void testCopyPropertiesWithEditable() throws Exception {
145 TestBean tb = new TestBean();
146 assertTrue("Name empty", tb.getName() == null);
147 tb.setAge(32);
148 tb.setTouchy("bla");
149 TestBean tb2 = new TestBean();
150 tb2.setName("rod");
151 assertTrue("Age empty", tb2.getAge() == 0);
152 assertTrue("Touchy empty", tb2.getTouchy() == null);
153
154
155 BeanUtils.copyProperties(tb, tb2, ITestBean.class);
156 assertTrue("Name copied", tb2.getName() == null);
157 assertTrue("Age copied", tb2.getAge() == 32);
158 assertTrue("Touchy still empty", tb2.getTouchy() == null);
159 }
160
161 @Test
162 public void testCopyPropertiesWithIgnore() throws Exception {
163 TestBean tb = new TestBean();
164 assertTrue("Name empty", tb.getName() == null);
165 tb.setAge(32);
166 tb.setTouchy("bla");
167 TestBean tb2 = new TestBean();
168 tb2.setName("rod");
169 assertTrue("Age empty", tb2.getAge() == 0);
170 assertTrue("Touchy empty", tb2.getTouchy() == null);
171
172
173 BeanUtils.copyProperties(tb, tb2, "spouse", "touchy", "age");
174 assertTrue("Name copied", tb2.getName() == null);
175 assertTrue("Age still empty", tb2.getAge() == 0);
176 assertTrue("Touchy still empty", tb2.getTouchy() == null);
177 }
178
179 @Test
180 public void testCopyPropertiesWithIgnoredNonExistingProperty() {
181 NameAndSpecialProperty source = new NameAndSpecialProperty();
182 source.setName("name");
183 TestBean target = new TestBean();
184 BeanUtils.copyProperties(source, target, "specialProperty");
185 assertEquals(target.getName(), "name");
186 }
187
188 @Test
189 public void testCopyPropertiesWithInvalidProperty() {
190 InvalidProperty source = new InvalidProperty();
191 source.setName("name");
192 source.setFlag1(true);
193 source.setFlag2(true);
194 InvalidProperty target = new InvalidProperty();
195 BeanUtils.copyProperties(source, target);
196 assertEquals(target.getName(), "name");
197 assertTrue(target.getFlag1());
198 assertTrue(target.getFlag2());
199 }
200
201 @Test
202 public void testResolveSimpleSignature() throws Exception {
203 Method desiredMethod = MethodSignatureBean.class.getMethod("doSomething");
204 assertSignatureEquals(desiredMethod, "doSomething");
205 assertSignatureEquals(desiredMethod, "doSomething()");
206 }
207
208 @Test
209 public void testResolveInvalidSignature() throws Exception {
210 try {
211 BeanUtils.resolveSignature("doSomething(", MethodSignatureBean.class);
212 fail("Should not be able to parse with opening but no closing paren.");
213 }
214 catch (IllegalArgumentException ex) {
215
216 }
217
218 try {
219 BeanUtils.resolveSignature("doSomething)", MethodSignatureBean.class);
220 fail("Should not be able to parse with closing but no opening paren.");
221 }
222 catch (IllegalArgumentException ex) {
223
224 }
225 }
226
227 @Test
228 public void testResolveWithAndWithoutArgList() throws Exception {
229 Method desiredMethod = MethodSignatureBean.class.getMethod("doSomethingElse", new Class[]{String.class, int.class});
230 assertSignatureEquals(desiredMethod, "doSomethingElse");
231 assertNull(BeanUtils.resolveSignature("doSomethingElse()", MethodSignatureBean.class));
232 }
233
234 @Test
235 public void testResolveTypedSignature() throws Exception {
236 Method desiredMethod = MethodSignatureBean.class.getMethod("doSomethingElse", new Class[]{String.class, int.class});
237 assertSignatureEquals(desiredMethod, "doSomethingElse(java.lang.String, int)");
238 }
239
240 @Test
241 public void testResolveOverloadedSignature() throws Exception {
242
243 Method desiredMethod = MethodSignatureBean.class.getMethod("overloaded");
244 assertSignatureEquals(desiredMethod, "overloaded()");
245
246
247 desiredMethod = MethodSignatureBean.class.getMethod("overloaded", new Class[]{String.class});
248 assertSignatureEquals(desiredMethod, "overloaded(java.lang.String)");
249
250
251 desiredMethod = MethodSignatureBean.class.getMethod("overloaded", new Class[]{String.class, BeanFactory.class});
252 assertSignatureEquals(desiredMethod, "overloaded(java.lang.String, org.springframework.beans.factory.BeanFactory)");
253 }
254
255 @Test
256 public void testResolveSignatureWithArray() throws Exception {
257 Method desiredMethod = MethodSignatureBean.class.getMethod("doSomethingWithAnArray", new Class[]{String[].class});
258 assertSignatureEquals(desiredMethod, "doSomethingWithAnArray(java.lang.String[])");
259
260 desiredMethod = MethodSignatureBean.class.getMethod("doSomethingWithAMultiDimensionalArray", new Class[]{String[][].class});
261 assertSignatureEquals(desiredMethod, "doSomethingWithAMultiDimensionalArray(java.lang.String[][])");
262 }
263
264 @Test
265 public void testSPR6063() {
266 PropertyDescriptor[] descrs = BeanUtils.getPropertyDescriptors(Bean.class);
267
268 PropertyDescriptor keyDescr = BeanUtils.getPropertyDescriptor(Bean.class, "value");
269 assertEquals(String.class, keyDescr.getPropertyType());
270 for (PropertyDescriptor propertyDescriptor : descrs) {
271 if (propertyDescriptor.getName().equals(keyDescr.getName())) {
272 assertEquals(propertyDescriptor.getName() + " has unexpected type",
273 keyDescr.getPropertyType(), propertyDescriptor.getPropertyType());
274 }
275 }
276 }
277
278 private void assertSignatureEquals(Method desiredMethod, String signature) {
279 assertEquals(desiredMethod, BeanUtils.resolveSignature(signature, MethodSignatureBean.class));
280 }
281
282
283 @SuppressWarnings("unused")
284 private static class NameAndSpecialProperty {
285
286 private String name;
287
288 private int specialProperty;
289
290 public void setName(String name) {
291 this.name = name;
292 }
293
294 public String getName() {
295 return this.name;
296 }
297
298 public void setSpecialProperty(int specialProperty) {
299 this.specialProperty = specialProperty;
300 }
301
302 public int getSpecialProperty() {
303 return specialProperty;
304 }
305 }
306
307
308 @SuppressWarnings("unused")
309 private static class InvalidProperty {
310
311 private String name;
312
313 private String value;
314
315 private boolean flag1;
316
317 private boolean flag2;
318
319 public void setName(String name) {
320 this.name = name;
321 }
322
323 public String getName() {
324 return this.name;
325 }
326
327 public void setValue(int value) {
328 this.value = Integer.toString(value);
329 }
330
331 public String getValue() {
332 return this.value;
333 }
334
335 public void setFlag1(boolean flag1) {
336 this.flag1 = flag1;
337 }
338
339 public Boolean getFlag1() {
340 return this.flag1;
341 }
342
343 public void setFlag2(Boolean flag2) {
344 this.flag2 = flag2;
345 }
346
347 public boolean getFlag2() {
348 return this.flag2;
349 }
350 }
351
352
353 @SuppressWarnings("unused")
354 private static class ContainerBean {
355
356 private ContainedBean[] containedBeans;
357
358 public ContainedBean[] getContainedBeans() {
359 return containedBeans;
360 }
361
362 public void setContainedBeans(ContainedBean[] containedBeans) {
363 this.containedBeans = containedBeans;
364 }
365 }
366
367
368 @SuppressWarnings("unused")
369 private static class ContainedBean {
370
371 private String name;
372
373 public String getName() {
374 return name;
375 }
376
377 public void setName(String name) {
378 this.name = name;
379 }
380 }
381
382
383 @SuppressWarnings("unused")
384 private static class MethodSignatureBean {
385
386 public void doSomething() {
387 }
388
389 public void doSomethingElse(String s, int x) {
390 }
391
392 public void overloaded() {
393 }
394
395 public void overloaded(String s) {
396 }
397
398 public void overloaded(String s, BeanFactory beanFactory) {
399 }
400
401 public void doSomethingWithAnArray(String[] strings) {
402 }
403
404 public void doSomethingWithAMultiDimensionalArray(String[][] strings) {
405 }
406 }
407
408
409 private interface MapEntry<K, V> {
410
411 K getKey();
412
413 void setKey(V value);
414
415 V getValue();
416
417 void setValue(V value);
418 }
419
420
421 private static class Bean implements MapEntry<String, String> {
422
423 private String key;
424
425 private String value;
426
427 @Override
428 public String getKey() {
429 return key;
430 }
431
432 @Override
433 public void setKey(String aKey) {
434 key = aKey;
435 }
436
437 @Override
438 public String getValue() {
439 return value;
440 }
441
442 @Override
443 public void setValue(String aValue) {
444 value = aValue;
445 }
446 }
447
448 }