View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.beanutils2;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertInstanceOf;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertNull;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  
27  import java.util.Calendar;
28  import java.util.HashMap;
29  import java.util.Locale;
30  import java.util.Map;
31  
32  import org.apache.commons.beanutils2.converters.ArrayConverter;
33  import org.apache.commons.beanutils2.converters.DateConverter;
34  import org.junit.jupiter.api.AfterEach;
35  import org.junit.jupiter.api.BeforeEach;
36  import org.junit.jupiter.api.Test;
37  
38  /**
39   * <p>
40   * Test Case for the BeanUtils class. The majority of these tests use instances of the TestBean class, so be sure to update the tests if you change the
41   * characteristics of that class.
42   * </p>
43   *
44   * <p>
45   * Template for this stolen from Craigs PropertyUtilsTestCase
46   * </p>
47   *
48   * <p>
49   * Note that the tests are dependant upon the static aspects (such as array sizes...) of the TestBean.java class, so ensure than all changes to TestBean are
50   * reflected here.
51   * </p>
52   *
53   * <p>
54   * So far, this test case has tests for the following methods of the {@code BeanUtils} class:
55   * </p>
56   * <ul>
57   * <li>getArrayProperty(Object bean, String name)</li>
58   * </ul>
59   */
60  public class BeanUtilsBeanTest {
61  
62      /**
63       * The test bean for each test.
64       */
65      protected TestBean bean;
66  
67      /**
68       * The set of properties that should be described.
69       */
70      protected String[] describes = { "booleanProperty", "booleanSecond", "byteProperty", "doubleProperty", "dupProperty", "floatProperty", "intArray",
71              // "intIndexed",
72              "longProperty", "listIndexed", "longProperty",
73              // "mappedProperty",
74              // "mappedIntProperty",
75              "nested", "nullProperty", "readOnlyProperty", "shortProperty", "stringArray",
76              // "stringIndexed",
77              "stringProperty" };
78  
79      /** Test Calendar value */
80      protected java.util.Calendar testCalendar;
81  
82      /** Test java.util.Date value */
83      protected java.util.Date testUtilDate;
84  
85      /** Test String Date value */
86      protected String testStringDate;
87  
88      // Ensure that the actual int[] matches the expected int[]
89      protected void checkIntArray(final int[] actual, final int[] expected) {
90          assertNotNull(actual, "actual array not null");
91          assertEquals(expected.length, actual.length, "actual array length");
92          for (int i = 0; i < actual.length; i++) {
93              assertEquals(expected[i], actual[i], "actual array value[" + i + "]");
94          }
95      }
96  
97      // Ensure that the actual Map matches the expected Map
98      protected void checkMap(final Map<?, ?> actual, final Map<?, ?> expected) {
99          assertNotNull(actual, "actual map not null");
100         assertEquals(expected.size(), actual.size(), "actual map size");
101         for (final Object key : expected.keySet()) {
102             assertEquals(expected.get(key), actual.get(key), "actual map value(" + key + ")");
103         }
104     }
105 
106     /**
107      * Use reflection to get the cause
108      */
109     private Throwable getCause(final Throwable t) throws Throwable {
110         return (Throwable) PropertyUtils.getProperty(t, "cause");
111     }
112 
113     /**
114      * Catch a cause, initialize using BeanUtils.initCause() and throw new exception
115      */
116     private void initCauseAndThrowException(final String parent, final String cause) throws Throwable {
117         try {
118             throwException(cause);
119         } catch (final Throwable e) {
120             throw new Exception(parent, e);
121         }
122     }
123 
124     /**
125      * Sets up instance variables required by this test case.
126      */
127     @BeforeEach
128     public void setUp() {
129         ConvertUtils.deregister();
130         BeanUtilsBean.setInstance(new BeanUtilsBean());
131         setUpShared();
132     }
133 
134     /**
135      * Shared Set up.
136      */
137     protected void setUpShared() {
138         bean = new TestBean();
139 
140         final DateConverter dateConverter = new DateConverter(null);
141         dateConverter.setLocale(Locale.US);
142         dateConverter.setPattern("dd.MM.yyyy");
143         ConvertUtils.register(dateConverter, java.util.Date.class);
144 
145         final ArrayConverter dateArrayConverter = new ArrayConverter(java.util.Date[].class, dateConverter, 0);
146         ConvertUtils.register(dateArrayConverter, java.util.Date[].class);
147 
148         testCalendar = Calendar.getInstance();
149         testCalendar.set(1992, 11, 28, 0, 0, 0);
150         testCalendar.set(Calendar.MILLISECOND, 0);
151         testUtilDate = testCalendar.getTime();
152         testStringDate = "28.12.1992";
153     }
154 
155     /**
156      * Tear down instance variables required by this test case.
157      */
158     @AfterEach
159     public void tearDown() {
160         bean = null;
161     }
162 
163     @Test
164     public void testArrayPropertyConversion() throws Exception {
165         final BeanUtilsBean beanUtils = new BeanUtilsBean(new ConvertUtilsBean(), new PropertyUtilsBean());
166 
167         final TestBean bean = new TestBean();
168         final String[] results = beanUtils.getArrayProperty(bean, "intArray");
169 
170         final int[] values = bean.getIntArray();
171         assertEquals(results.length, values.length, "Converted array size not equal to property array size.");
172         for (int i = 0, size = values.length; i < size; i++) {
173             assertEquals(values[i] + "", results[i], "Value " + i + " incorrectly converted ");
174         }
175     }
176 
177     /**
178      * Test the copyProperties() method from a DynaBean.
179      */
180     @Test
181     public void testCopyPropertiesDynaBean() throws Exception {
182 
183         // Set up an origin bean with customized properties
184         final DynaClass dynaClass = DynaBeanUtilsTest.createDynaClass();
185         DynaBean orig = null;
186         orig = dynaClass.newInstance();
187         orig.set("booleanProperty", Boolean.FALSE);
188         orig.set("byteProperty", Byte.valueOf((byte) 111));
189         orig.set("doubleProperty", Double.valueOf(333.33));
190         orig.set("dupProperty", new String[] { "New 0", "New 1", "New 2" });
191         orig.set("intArray", new int[] { 100, 200, 300 });
192         orig.set("intProperty", Integer.valueOf(333));
193         orig.set("longProperty", Long.valueOf(3333));
194         orig.set("shortProperty", Short.valueOf((short) 33));
195         orig.set("stringArray", new String[] { "New 0", "New 1" });
196         orig.set("stringProperty", "Custom string");
197 
198         // Copy the origin bean to our destination test bean
199         BeanUtils.copyProperties(bean, orig);
200 
201         // Validate the results for scalar properties
202         assertEquals(false, bean.getBooleanProperty(), "Copied boolean property");
203         assertEquals((byte) 111, bean.getByteProperty(), "Copied byte property");
204         assertEquals(333.33, bean.getDoubleProperty(), 0.005, "Copied double property");
205         assertEquals(333, bean.getIntProperty(), "Copied int property");
206         assertEquals(3333, bean.getLongProperty(), "Copied long property");
207         assertEquals((short) 33, bean.getShortProperty(), "Copied short property");
208         assertEquals("Custom string", bean.getStringProperty(), "Copied string property");
209 
210         // Validate the results for array properties
211         final String[] dupProperty = bean.getDupProperty();
212         assertNotNull(dupProperty, "dupProperty present");
213         assertEquals(3, dupProperty.length, "dupProperty length");
214         assertEquals("New 0", dupProperty[0], "dupProperty[0]");
215         assertEquals("New 1", dupProperty[1], "dupProperty[1]");
216         assertEquals("New 2", dupProperty[2], "dupProperty[2]");
217         final int[] intArray = bean.getIntArray();
218         assertNotNull(intArray, "intArray present");
219         assertEquals(3, intArray.length, "intArray length");
220         assertEquals(100, intArray[0], "intArray[0]");
221         assertEquals(200, intArray[1], "intArray[1]");
222         assertEquals(300, intArray[2], "intArray[2]");
223         final String[] stringArray = bean.getStringArray();
224         assertNotNull(stringArray, "stringArray present");
225         assertEquals(2, stringArray.length, "stringArray length");
226         assertEquals("New 0", stringArray[0], "stringArray[0]");
227         assertEquals("New 1", stringArray[1], "stringArray[1]");
228 
229     }
230 
231     /**
232      * Test copyProperties() when the origin is a {@code Map}.
233      */
234     @Test
235     public void testCopyPropertiesMap() throws Exception {
236 
237         final Map<String, Object> map = new HashMap<>();
238         map.put("booleanProperty", "false");
239         map.put("byteProperty", "111");
240         map.put("doubleProperty", "333.0");
241         map.put("dupProperty", new String[] { "New 0", "New 1", "New 2" });
242         map.put("floatProperty", "222.0");
243         map.put("intArray", new String[] { "0", "100", "200" });
244         map.put("intProperty", "111");
245         map.put("longProperty", "444");
246         map.put("shortProperty", "555");
247         map.put("stringProperty", "New String Property");
248 
249         BeanUtils.copyProperties(bean, map);
250 
251         // Scalar properties
252         assertEquals(false, bean.getBooleanProperty(), "booleanProperty");
253         assertEquals((byte) 111, bean.getByteProperty(), "byteProperty");
254         assertEquals(333.0, bean.getDoubleProperty(), 0.005, "doubleProperty");
255         assertEquals((float) 222.0, bean.getFloatProperty(), (float) 0.005, "floatProperty");
256         assertEquals(111, bean.getIntProperty(), "longProperty");
257         assertEquals(444, bean.getLongProperty(), "longProperty");
258         assertEquals((short) 555, bean.getShortProperty(), "shortProperty");
259         assertEquals("New String Property", bean.getStringProperty(), "stringProperty");
260 
261         // Indexed Properties
262         final String[] dupProperty = bean.getDupProperty();
263         assertNotNull(dupProperty, "dupProperty present");
264         assertEquals(3, dupProperty.length, "dupProperty length");
265         assertEquals("New 0", dupProperty[0], "dupProperty[0]");
266         assertEquals("New 1", dupProperty[1], "dupProperty[1]");
267         assertEquals("New 2", dupProperty[2], "dupProperty[2]");
268         final int[] intArray = bean.getIntArray();
269         assertNotNull(intArray, "intArray present");
270         assertEquals(3, intArray.length, "intArray length");
271         assertEquals(0, intArray[0], "intArray[0]");
272         assertEquals(100, intArray[1], "intArray[1]");
273         assertEquals(200, intArray[2], "intArray[2]");
274 
275     }
276 
277     /**
278      * Test the copyProperties() method from a standard JavaBean.
279      */
280     @Test
281     public void testCopyPropertiesStandard() throws Exception {
282 
283         // Set up an origin bean with customized properties
284         final TestBean orig = new TestBean();
285         orig.setBooleanProperty(false);
286         orig.setByteProperty((byte) 111);
287         orig.setDoubleProperty(333.33);
288         orig.setDupProperty(new String[] { "New 0", "New 1", "New 2" });
289         orig.setIntArray(new int[] { 100, 200, 300 });
290         orig.setIntProperty(333);
291         orig.setLongProperty(3333);
292         orig.setShortProperty((short) 33);
293         orig.setStringArray(new String[] { "New 0", "New 1" });
294         orig.setStringProperty("Custom string");
295 
296         // Copy the origin bean to our destination test bean
297         BeanUtils.copyProperties(bean, orig);
298 
299         // Validate the results for scalar properties
300         assertEquals(false, bean.getBooleanProperty(), "Copied boolean property");
301         assertEquals((byte) 111, bean.getByteProperty(), "Copied byte property");
302         assertEquals(333.33, bean.getDoubleProperty(), 0.005, "Copied double property");
303         assertEquals(333, bean.getIntProperty(), "Copied int property");
304         assertEquals(3333, bean.getLongProperty(), "Copied long property");
305         assertEquals((short) 33, bean.getShortProperty(), "Copied short property");
306         assertEquals("Custom string", bean.getStringProperty(), "Copied string property");
307 
308         // Validate the results for array properties
309         final String[] dupProperty = bean.getDupProperty();
310         assertNotNull(dupProperty, "dupProperty present");
311         assertEquals(3, dupProperty.length, "dupProperty length");
312         assertEquals("New 0", dupProperty[0], "dupProperty[0]");
313         assertEquals("New 1", dupProperty[1], "dupProperty[1]");
314         assertEquals("New 2", dupProperty[2], "dupProperty[2]");
315         final int[] intArray = bean.getIntArray();
316         assertNotNull(intArray, "intArray present");
317         assertEquals(3, intArray.length, "intArray length");
318         assertEquals(100, intArray[0], "intArray[0]");
319         assertEquals(200, intArray[1], "intArray[1]");
320         assertEquals(300, intArray[2], "intArray[2]");
321         final String[] stringArray = bean.getStringArray();
322         assertNotNull(stringArray, "stringArray present");
323         assertEquals(2, stringArray.length, "stringArray length");
324         assertEquals("New 0", stringArray[0], "stringArray[0]");
325         assertEquals("New 1", stringArray[1], "stringArray[1]");
326 
327     }
328 
329     /**
330      * Test narrowing and widening conversions on byte.
331      */
332     @Test
333     public void testCopyPropertyByte() throws Exception {
334 
335         BeanUtils.copyProperty(bean, "byteProperty", Byte.valueOf((byte) 123));
336         assertEquals((byte) 123, bean.getByteProperty());
337         BeanUtils.copyProperty(bean, "byteProperty", Double.valueOf(123));
338         assertEquals((byte) 123, bean.getByteProperty());
339         BeanUtils.copyProperty(bean, "byteProperty", Float.valueOf(123));
340         assertEquals((byte) 123, bean.getByteProperty());
341         BeanUtils.copyProperty(bean, "byteProperty", Integer.valueOf(123));
342         assertEquals((byte) 123, bean.getByteProperty());
343         BeanUtils.copyProperty(bean, "byteProperty", Long.valueOf(123));
344         assertEquals((byte) 123, bean.getByteProperty());
345         BeanUtils.copyProperty(bean, "byteProperty", Short.valueOf((short) 123));
346         assertEquals((byte) 123, bean.getByteProperty());
347 
348     }
349 
350     /**
351      * Test {@code copyProperty()} conversion.
352      */
353     @Test
354     public void testCopyPropertyConvert() throws Exception {
355         BeanUtils.copyProperty(bean, "dateProperty", testCalendar);
356         assertEquals(testUtilDate, bean.getDateProperty(), "Calendar --> java.util.Date");
357     }
358 
359     /**
360      * Test {@code copyProperty()} converting from a String.
361      */
362     @Test
363     public void testCopyPropertyConvertFromString() throws Exception {
364         BeanUtils.copyProperty(bean, "dateProperty", testStringDate);
365         assertEquals(testUtilDate, bean.getDateProperty(), "String --> java.util.Date");
366     }
367 
368     /**
369      * Test {@code copyProperty()} converting to a String.
370      */
371     @Test
372     public void testCopyPropertyConvertToString() throws Exception {
373         BeanUtils.copyProperty(bean, "stringProperty", testUtilDate);
374         assertEquals(testStringDate, bean.getStringProperty(), "java.util.Date --> String");
375     }
376 
377     /**
378      * Test {@code copyProperty()} converting to a String.
379      */
380     @Test
381     public void testCopyPropertyConvertToStringArray() throws Exception {
382         bean.setStringArray(null);
383         BeanUtils.copyProperty(bean, "stringArray", new java.util.Date[] { testUtilDate });
384         assertEquals(1, bean.getStringArray().length, "java.util.Date[] --> String[] length");
385         assertEquals(testStringDate, bean.getStringArray()[0], "java.util.Date[] --> String[] value ");
386     }
387 
388     /**
389      * Test {@code copyProperty()} converting to a String on indexed property
390      */
391     @Test
392     public void testCopyPropertyConvertToStringIndexed() throws Exception {
393         bean.setStringArray(new String[1]);
394         BeanUtils.copyProperty(bean, "stringArray[0]", testUtilDate);
395         assertEquals(1, bean.getStringArray().length, "java.util.Date[] --> String[] length");
396         assertEquals(testStringDate, bean.getStringArray()[0], "java.util.Date[] --> String[] value ");
397     }
398 
399     /**
400      * Test narrowing and widening conversions on double.
401      */
402     @Test
403     public void testCopyPropertyDouble() throws Exception {
404 
405         BeanUtils.copyProperty(bean, "doubleProperty", Byte.valueOf((byte) 123));
406         assertEquals(123, bean.getDoubleProperty(), 0.005);
407         BeanUtils.copyProperty(bean, "doubleProperty", Double.valueOf(123));
408         assertEquals(123, bean.getDoubleProperty(), 0.005);
409         BeanUtils.copyProperty(bean, "doubleProperty", Float.valueOf(123));
410         assertEquals(123, bean.getDoubleProperty(), 0.005);
411         BeanUtils.copyProperty(bean, "doubleProperty", Integer.valueOf(123));
412         assertEquals(123, bean.getDoubleProperty(), 0.005);
413         BeanUtils.copyProperty(bean, "doubleProperty", Long.valueOf(123));
414         assertEquals(123, bean.getDoubleProperty(), 0.005);
415         BeanUtils.copyProperty(bean, "doubleProperty", Short.valueOf((short) 123));
416         assertEquals(123, bean.getDoubleProperty(), 0.005);
417 
418     }
419 
420     /**
421      * Test narrowing and widening conversions on float.
422      */
423     @Test
424     public void testCopyPropertyFloat() throws Exception {
425 
426         BeanUtils.copyProperty(bean, "floatProperty", Byte.valueOf((byte) 123));
427         assertEquals(123, bean.getFloatProperty(), 0.005);
428         BeanUtils.copyProperty(bean, "floatProperty", Double.valueOf(123));
429         assertEquals(123, bean.getFloatProperty(), 0.005);
430         BeanUtils.copyProperty(bean, "floatProperty", Float.valueOf(123));
431         assertEquals(123, bean.getFloatProperty(), 0.005);
432         BeanUtils.copyProperty(bean, "floatProperty", Integer.valueOf(123));
433         assertEquals(123, bean.getFloatProperty(), 0.005);
434         BeanUtils.copyProperty(bean, "floatProperty", Long.valueOf(123));
435         assertEquals(123, bean.getFloatProperty(), 0.005);
436         BeanUtils.copyProperty(bean, "floatProperty", Short.valueOf((short) 123));
437         assertEquals(123, bean.getFloatProperty(), 0.005);
438 
439     }
440 
441     /**
442      * Test narrowing and widening conversions on int.
443      */
444     @Test
445     public void testCopyPropertyInteger() throws Exception {
446 
447         BeanUtils.copyProperty(bean, "longProperty", Byte.valueOf((byte) 123));
448         assertEquals(123, bean.getIntProperty());
449         BeanUtils.copyProperty(bean, "longProperty", Double.valueOf(123));
450         assertEquals(123, bean.getIntProperty());
451         BeanUtils.copyProperty(bean, "longProperty", Float.valueOf(123));
452         assertEquals(123, bean.getIntProperty());
453         BeanUtils.copyProperty(bean, "longProperty", Integer.valueOf(123));
454         assertEquals(123, bean.getIntProperty());
455         BeanUtils.copyProperty(bean, "longProperty", Long.valueOf(123));
456         assertEquals(123, bean.getIntProperty());
457         BeanUtils.copyProperty(bean, "longProperty", Short.valueOf((short) 123));
458         assertEquals(123, bean.getIntProperty());
459 
460     }
461 
462     /**
463      * Test narrowing and widening conversions on long.
464      */
465     @Test
466     public void testCopyPropertyLong() throws Exception {
467 
468         BeanUtils.copyProperty(bean, "longProperty", Byte.valueOf((byte) 123));
469         assertEquals(123, bean.getLongProperty());
470         BeanUtils.copyProperty(bean, "longProperty", Double.valueOf(123));
471         assertEquals(123, bean.getLongProperty());
472         BeanUtils.copyProperty(bean, "longProperty", Float.valueOf(123));
473         assertEquals(123, bean.getLongProperty());
474         BeanUtils.copyProperty(bean, "longProperty", Integer.valueOf(123));
475         assertEquals(123, bean.getLongProperty());
476         BeanUtils.copyProperty(bean, "longProperty", Long.valueOf(123));
477         assertEquals(123, bean.getLongProperty());
478         BeanUtils.copyProperty(bean, "longProperty", Short.valueOf((short) 123));
479         assertEquals(123, bean.getLongProperty());
480 
481     }
482 
483     /**
484      * Test copying a property using a nested indexed array expression, with and without conversions.
485      */
486     @Test
487     public void testCopyPropertyNestedIndexedArray() throws Exception {
488 
489         final int[] origArray = { 0, 10, 20, 30, 40 };
490         final int[] intArray = { 0, 0, 0 };
491         bean.getNested().setIntArray(intArray);
492         final int[] intChanged = { 0, 0, 0 };
493 
494         // No conversion required
495         BeanUtils.copyProperty(bean, "nested.intArray[1]", Integer.valueOf(1));
496         checkIntArray(bean.getIntArray(), origArray);
497         intChanged[1] = 1;
498         checkIntArray(bean.getNested().getIntArray(), intChanged);
499 
500         // Widening conversion required
501         BeanUtils.copyProperty(bean, "nested.intArray[1]", Byte.valueOf((byte) 2));
502         checkIntArray(bean.getIntArray(), origArray);
503         intChanged[1] = 2;
504         checkIntArray(bean.getNested().getIntArray(), intChanged);
505 
506         // Narrowing conversion required
507         BeanUtils.copyProperty(bean, "nested.intArray[1]", Long.valueOf(3));
508         checkIntArray(bean.getIntArray(), origArray);
509         intChanged[1] = 3;
510         checkIntArray(bean.getNested().getIntArray(), intChanged);
511 
512         // String conversion required
513         BeanUtils.copyProperty(bean, "nested.intArray[1]", "4");
514         checkIntArray(bean.getIntArray(), origArray);
515         intChanged[1] = 4;
516         checkIntArray(bean.getNested().getIntArray(), intChanged);
517 
518     }
519 
520     /**
521      * Test copying a property using a nested mapped map property.
522      */
523     @Test
524     public void testCopyPropertyNestedMappedMap() throws Exception {
525 
526         final Map<String, Object> origMap = new HashMap<>();
527         origMap.put("First Key", "First Value");
528         origMap.put("Second Key", "Second Value");
529         final Map<String, Object> changedMap = new HashMap<>();
530         changedMap.put("First Key", "First Value");
531         changedMap.put("Second Key", "Second Value");
532 
533         // No conversion required
534         BeanUtils.copyProperty(bean, "nested.mapProperty(Second Key)", "New Second Value");
535         checkMap(bean.getMapProperty(), origMap);
536         changedMap.put("Second Key", "New Second Value");
537         checkMap(bean.getNested().getMapProperty(), changedMap);
538 
539     }
540 
541     /**
542      * Test copying a property using a nested simple expression, with and without conversions.
543      */
544     @Test
545     public void testCopyPropertyNestedSimple() throws Exception {
546 
547         bean.setIntProperty(0);
548         bean.getNested().setIntProperty(0);
549 
550         // No conversion required
551         BeanUtils.copyProperty(bean, "nested.intProperty", Integer.valueOf(1));
552         assertNotNull(bean.getNested());
553         assertEquals(0, bean.getIntProperty());
554         assertEquals(1, bean.getNested().getIntProperty());
555 
556         // Widening conversion required
557         BeanUtils.copyProperty(bean, "nested.intProperty", Byte.valueOf((byte) 2));
558         assertNotNull(bean.getNested());
559         assertEquals(0, bean.getIntProperty());
560         assertEquals(2, bean.getNested().getIntProperty());
561 
562         // Narrowing conversion required
563         BeanUtils.copyProperty(bean, "nested.intProperty", Long.valueOf(3));
564         assertNotNull(bean.getNested());
565         assertEquals(0, bean.getIntProperty());
566         assertEquals(3, bean.getNested().getIntProperty());
567 
568         // String conversion required
569         BeanUtils.copyProperty(bean, "nested.intProperty", "4");
570         assertNotNull(bean.getNested());
571         assertEquals(0, bean.getIntProperty());
572         assertEquals(4, bean.getNested().getIntProperty());
573 
574     }
575 
576     /**
577      * Test copying a null property value.
578      */
579     @Test
580     public void testCopyPropertyNull() throws Exception {
581 
582         bean.setNullProperty("non-null value");
583         BeanUtils.copyProperty(bean, "nullProperty", null);
584         assertNull(bean.getNullProperty(), "nullProperty is null");
585 
586     }
587 
588     /**
589      * Test narrowing and widening conversions on short.
590      */
591     @Test
592     public void testCopyPropertyShort() throws Exception {
593 
594         BeanUtils.copyProperty(bean, "shortProperty", Byte.valueOf((byte) 123));
595         assertEquals((short) 123, bean.getShortProperty());
596         BeanUtils.copyProperty(bean, "shortProperty", Double.valueOf(123));
597         assertEquals((short) 123, bean.getShortProperty());
598         BeanUtils.copyProperty(bean, "shortProperty", Float.valueOf(123));
599         assertEquals((short) 123, bean.getShortProperty());
600         BeanUtils.copyProperty(bean, "shortProperty", Integer.valueOf(123));
601         assertEquals((short) 123, bean.getShortProperty());
602         BeanUtils.copyProperty(bean, "shortProperty", Long.valueOf(123));
603         assertEquals((short) 123, bean.getShortProperty());
604         BeanUtils.copyProperty(bean, "shortProperty", Short.valueOf((short) 123));
605         assertEquals((short) 123, bean.getShortProperty());
606 
607     }
608 
609     /**
610      * Test copying a new value to a write-only property, with and without conversions.
611      */
612     @Test
613     public void testCopyPropertyWriteOnly() throws Exception {
614 
615         bean.setWriteOnlyProperty("Original value");
616 
617         // No conversion required
618         BeanUtils.copyProperty(bean, "writeOnlyProperty", "New value");
619         assertEquals("New value", bean.getWriteOnlyPropertyValue());
620 
621         // Integer->String conversion required
622         BeanUtils.copyProperty(bean, "writeOnlyProperty", Integer.valueOf(123));
623         assertEquals("123", bean.getWriteOnlyPropertyValue());
624 
625     }
626 
627     /**
628      * Test the describe() method.
629      */
630     @Test
631     public void testDescribe() throws Exception {
632         assertTrue(BeanUtils.describe(null).isEmpty());
633         Map<String, String> map = null;
634         map = BeanUtils.describe(bean);
635         // Verify existence of all the properties that should be present
636         for (final String describe : describes) {
637             assertTrue(map.containsKey(describe), "Property '" + describe + "' is present");
638         }
639         assertTrue(!map.containsKey("writeOnlyProperty"), "Property 'writeOnlyProperty' is not present");
640         // Verify the values of scalar properties
641         assertEquals("true", map.get("booleanProperty"), "Value of 'booleanProperty'");
642         assertEquals("121", map.get("byteProperty"), "Value of 'byteProperty'");
643         assertEquals("321.0", map.get("doubleProperty"), "Value of 'doubleProperty'");
644         assertEquals("123.0", map.get("floatProperty"), "Value of 'floatProperty'");
645         assertEquals("123", map.get("intProperty"), "Value of 'intProperty'");
646         assertEquals("321", map.get("longProperty"), "Value of 'longProperty'");
647         assertEquals("987", map.get("shortProperty"), "Value of 'shortProperty'");
648         assertEquals("This is a string", map.get("stringProperty"), "Value of 'stringProperty'");
649     }
650 
651     /**
652      * tests the string and int arrays of TestBean
653      */
654     @Test
655     public void testGetArrayProperty() throws Exception {
656         String[] arr = BeanUtils.getArrayProperty(bean, "stringArray");
657         final String[] comp = bean.getStringArray();
658 
659         assertEquals(comp.length, arr.length, "String array length = " + comp.length);
660 
661         arr = BeanUtils.getArrayProperty(bean, "intArray");
662         final int[] iarr = bean.getIntArray();
663 
664         assertEquals(iarr.length, arr.length, "String array length = " + iarr.length);
665 
666         // Test property which isn't array or collection
667         arr = BeanUtils.getArrayProperty(bean, "shortProperty");
668         final String shortAsString = "" + bean.getShortProperty();
669         assertEquals(1, arr.length, "Short List Test lth");
670         assertEquals(shortAsString, arr[0], "Short Test value");
671 
672         // Test comma delimited list
673         bean.setStringProperty("ABC");
674         arr = BeanUtils.getArrayProperty(bean, "stringProperty");
675         assertEquals(1, arr.length, "Delimited List Test lth");
676         assertEquals("ABC", arr[0], "Delimited List Test value1");
677     }
678 
679     /**
680      * Test {@code getArrayProperty()} converting to a String.
681      */
682     @Test
683     public void testGetArrayPropertyDate() throws Exception {
684         String[] value = null;
685         bean.setDateArrayProperty(new java.util.Date[] { testUtilDate });
686         value = BeanUtils.getArrayProperty(bean, "dateArrayProperty");
687         assertEquals(1, value.length, "java.util.Date[] --> String[] length");
688         assertEquals(testStringDate, value[0], "java.util.Date[] --> String[] value ");
689     }
690 
691     /**
692      * tests getting a 'whatever' property
693      */
694     @Test
695     public void testGetGeneralProperty() throws Exception {
696         final String val = BeanUtils.getProperty(bean, "nested.intIndexed[2]");
697         final String comp = String.valueOf(bean.getIntIndexed(2));
698 
699         assertEquals(val, comp, "nested.intIndexed[2] == " + comp);
700     }
701 
702     /**
703      * tests getting an indexed property
704      */
705     @Test
706     public void testGetIndexedProperty1() throws Exception {
707         String val = BeanUtils.getIndexedProperty(bean, "intIndexed[3]");
708         String comp = String.valueOf(bean.getIntIndexed(3));
709         assertEquals(val, comp, "intIndexed[3] == " + comp);
710 
711         val = BeanUtils.getIndexedProperty(bean, "stringIndexed[3]");
712         comp = bean.getStringIndexed(3);
713         assertEquals(val, comp, "stringIndexed[3] == " + comp);
714     }
715 
716     /**
717      * tests getting an indexed property
718      */
719     @Test
720     public void testGetIndexedProperty2() throws Exception {
721         String val = BeanUtils.getIndexedProperty(bean, "intIndexed", 3);
722         String comp = String.valueOf(bean.getIntIndexed(3));
723 
724         assertEquals(val, comp, "intIndexed,3 == " + comp);
725 
726         val = BeanUtils.getIndexedProperty(bean, "stringIndexed", 3);
727         comp = bean.getStringIndexed(3);
728 
729         assertEquals(val, comp, "stringIndexed,3 == " + comp);
730     }
731 
732     /**
733      * Test {@code getArrayProperty()} converting to a String.
734      */
735     @Test
736     public void testGetIndexedPropertyDate() throws Exception {
737         String value = null;
738         bean.setDateArrayProperty(new java.util.Date[] { testUtilDate });
739         value = BeanUtils.getIndexedProperty(bean, "dateArrayProperty[0]");
740         assertEquals(testStringDate, value, "java.util.Date[0] --> String");
741     }
742 
743     @Test
744     public void testGetMappedProperty2Args() throws Exception {
745         assertThrows(NullPointerException.class, () -> BeanUtils.getMappedProperty(null, null));
746         assertThrows(NullPointerException.class, () -> BeanUtils.getMappedProperty(null, ""));
747         assertThrows(NullPointerException.class, () -> BeanUtils.getMappedProperty("", null));
748     }
749 
750     @Test
751     public void testGetMappedProperty3Args() throws Exception {
752         assertThrows(NullPointerException.class, () -> BeanUtils.getMappedProperty(null, null));
753         assertThrows(NullPointerException.class, () -> BeanUtils.getMappedProperty(null, "", null));
754         assertThrows(NullPointerException.class, () -> BeanUtils.getMappedProperty("", null, null));
755     }
756 
757     /**
758      * tests getting a nested property
759      */
760     @Test
761     public void testGetNestedProperty() throws Exception {
762         final String val = BeanUtils.getNestedProperty(bean, "nested.stringProperty");
763         final String comp = bean.getNested().getStringProperty();
764         assertEquals(val, comp, "nested.StringProperty == " + comp);
765     }
766 
767     /**
768      * tests getting a 'whatever' property
769      */
770     @Test
771     public void testGetSimpleProperty() throws Exception {
772         final String val = BeanUtils.getSimpleProperty(bean, "shortProperty");
773         final String comp = String.valueOf(bean.getShortProperty());
774 
775         assertEquals(val, comp, "shortProperty == " + comp);
776     }
777 
778     /**
779      * Test {@code getSimpleProperty()} converting to a String.
780      */
781     @Test
782     public void testGetSimplePropertyDate() throws Exception {
783         String value = null;
784         bean.setDateProperty(testUtilDate);
785         value = BeanUtils.getSimpleProperty(bean, "dateProperty");
786         assertEquals(testStringDate, value, "java.util.Date --> String");
787     }
788 
789     @Test
790     public void testMappedProperty() throws Exception {
791         final MappedPropertyTestBean bean = new MappedPropertyTestBean();
792         BeanUtils.setProperty(bean, "mapproperty(this.that.the-other)", "some.dotty.value");
793         assertEquals("some.dotty.value", bean.getMapproperty("this.that.the-other"), "Mapped property set correctly");
794     }
795 
796     @Test
797     public void testPopulate() throws Exception {
798         BeanUtilsBean.getInstance().populate(null, null);
799         BeanUtilsBean.getInstance().populate("", null);
800         BeanUtilsBean.getInstance().populate(null, new HashMap<>());
801     }
802 
803     /**
804      * Test populate() method on individual array elements.
805      */
806     @Test
807     public void testPopulateArrayElements() throws Exception {
808         final HashMap<String, Object> map = new HashMap<>();
809         map.put("intIndexed[0]", "100");
810         map.put("intIndexed[2]", "120");
811         map.put("intIndexed[4]", "140");
812 
813         BeanUtils.populate(bean, map);
814 
815         assertEquals(100, bean.getIntIndexed(0), "intIndexed[0] is 100");
816         assertEquals(10, bean.getIntIndexed(1), "intIndexed[1] is 10");
817         assertEquals(120, bean.getIntIndexed(2), "intIndexed[2] is 120");
818         assertEquals(30, bean.getIntIndexed(3), "intIndexed[3] is 30");
819         assertEquals(140, bean.getIntIndexed(4), "intIndexed[4] is 140");
820 
821         map.clear();
822         map.put("stringIndexed[1]", "New String 1");
823         map.put("stringIndexed[3]", "New String 3");
824 
825         BeanUtils.populate(bean, map);
826 
827         assertEquals("String 0", bean.getStringIndexed(0), "stringIndexed[0] is \"String 0\"");
828         assertEquals("New String 1", bean.getStringIndexed(1), "stringIndexed[1] is \"New String 1\"");
829         assertEquals("String 2", bean.getStringIndexed(2), "stringIndexed[2] is \"String 2\"");
830         assertEquals("New String 3", bean.getStringIndexed(3), "stringIndexed[3] is \"New String 3\"");
831         assertEquals("String 4", bean.getStringIndexed(4), "stringIndexed[4] is \"String 4\"");
832     }
833 
834     /**
835      * Test populate() method on array properties as a whole.
836      */
837     @Test
838     public void testPopulateArrayProperties() throws Exception {
839         final HashMap<String, Object> map = new HashMap<>();
840         int[] intArray = { 123, 456, 789 };
841         map.put("intArray", intArray);
842         String[] stringArray = { "New String 0", "New String 1" };
843         map.put("stringArray", stringArray);
844 
845         BeanUtils.populate(bean, map);
846 
847         intArray = bean.getIntArray();
848         assertNotNull(intArray, "intArray is present");
849         assertEquals(3, intArray.length, "intArray length");
850         assertEquals(123, intArray[0], "intArray[0]");
851         assertEquals(456, intArray[1], "intArray[1]");
852         assertEquals(789, intArray[2], "intArray[2]");
853         stringArray = bean.getStringArray();
854         assertNotNull(stringArray, "stringArray is present");
855         assertEquals(2, stringArray.length, "stringArray length");
856         assertEquals("New String 0", stringArray[0], "stringArray[0]");
857         assertEquals("New String 1", stringArray[1], "stringArray[1]");
858     }
859 
860     /**
861      * Test populate() on mapped properties.
862      */
863     @Test
864     public void testPopulateMapped() throws Exception {
865         final HashMap<String, Object> map = new HashMap<>();
866         map.put("mappedProperty(First Key)", "New First Value");
867         map.put("mappedProperty(Third Key)", "New Third Value");
868 
869         BeanUtils.populate(bean, map);
870 
871         assertEquals("New First Value", bean.getMappedProperty("First Key"), "mappedProperty(First Key)");
872         assertEquals("Second Value", bean.getMappedProperty("Second Key"), "mappedProperty(Second Key)");
873         assertEquals("New Third Value", bean.getMappedProperty("Third Key"), "mappedProperty(Third Key)");
874         assertNull(bean.getMappedProperty("Fourth Key"), "mappedProperty(Fourth Key");
875     }
876 
877     /**
878      * Test populate() method on nested properties.
879      */
880     @Test
881     public void testPopulateNested() throws Exception {
882         final HashMap<String, Object> map = new HashMap<>();
883         map.put("nested.booleanProperty", "false");
884         // booleanSecond is left at true
885         map.put("nested.doubleProperty", "432.0");
886         // floatProperty is left at 123.0
887         map.put("nested.intProperty", "543");
888         // longProperty is left at 321
889         map.put("nested.shortProperty", "654");
890         // stringProperty is left at "This is a string"
891         map.put("nested.writeOnlyProperty", "New writeOnlyProperty value");
892 
893         BeanUtils.populate(bean, map);
894 
895         assertTrue(!bean.getNested().getBooleanProperty(), "booleanProperty is false");
896         assertTrue(bean.getNested().isBooleanSecond(), "booleanSecond is true");
897         assertEquals(432.0, bean.getNested().getDoubleProperty(), 0.005, "doubleProperty is 432.0");
898         assertEquals((float) 123.0, bean.getNested().getFloatProperty(), (float) 0.005, "floatProperty is 123.0");
899         assertEquals(543, bean.getNested().getIntProperty(), "intProperty is 543");
900         assertEquals(321, bean.getNested().getLongProperty(), "longProperty is 321");
901         assertEquals((short) 654, bean.getNested().getShortProperty(), "shortProperty is 654");
902         assertEquals("This is a string", bean.getNested().getStringProperty(), "stringProperty is \"This is a string\"");
903         assertEquals("New writeOnlyProperty value", bean.getNested().getWriteOnlyPropertyValue(), "writeOnlyProperty is \"New writeOnlyProperty value\"");
904     }
905 
906     /**
907      * Test populate() method on scalar properties.
908      */
909     @Test
910     public void testPopulateScalar() throws Exception {
911         bean.setNullProperty("Non-null value");
912 
913         final HashMap<String, Object> map = new HashMap<>();
914         map.put("booleanProperty", "false");
915         // booleanSecond is left at true
916         map.put("byteProperty", "111");
917         map.put("doubleProperty", "432.0");
918         // floatProperty is left at 123.0
919         map.put("intProperty", "543");
920         map.put("longProperty", "");
921         map.put("nullProperty", null);
922         map.put("shortProperty", "654");
923         // stringProperty is left at "This is a string"
924         map.put("writeOnlyProperty", "New writeOnlyProperty value");
925         map.put("readOnlyProperty", "New readOnlyProperty value");
926 
927         BeanUtils.populate(bean, map);
928 
929         assertTrue(!bean.getBooleanProperty(), "booleanProperty is false");
930         assertTrue(bean.isBooleanSecond(), "booleanSecond is true");
931         assertEquals((byte) 111, bean.getByteProperty(), "byteProperty is 111");
932         assertEquals(432.0, bean.getDoubleProperty(), 0.005, "doubleProperty is 432.0");
933         assertEquals((float) 123.0, bean.getFloatProperty(), (float) 0.005, "floatProperty is 123.0");
934         assertEquals(543, bean.getIntProperty(), "intProperty is 543");
935         assertEquals(0, bean.getLongProperty(), "longProperty is 0");
936         assertNull(bean.getNullProperty(), "nullProperty is null");
937         assertEquals((short) 654, bean.getShortProperty(), "shortProperty is 654");
938         assertEquals("This is a string", bean.getStringProperty(), "stringProperty is \"This is a string\"");
939         assertEquals("New writeOnlyProperty value", bean.getWriteOnlyPropertyValue(), "writeOnlyProperty is \"New writeOnlyProperty value\"");
940         assertEquals("Read Only String Property", bean.getReadOnlyProperty(), "readOnlyProperty is \"Read Only String Property\"");
941     }
942 
943     /** Tests that separate instances can register separate instances */
944     @Test
945     public void testSeparateInstances() throws Exception {
946         final BeanUtilsBean utilsOne = new BeanUtilsBean(new ConvertUtilsBean(), new PropertyUtilsBean());
947         final BeanUtilsBean utilsTwo = new BeanUtilsBean(new ConvertUtilsBean(), new PropertyUtilsBean());
948 
949         final TestBean bean = new TestBean();
950 
951         // Make sure what we're testing works
952         bean.setBooleanProperty(false);
953         utilsOne.setProperty(bean, "booleanProperty", "true");
954         assertEquals(bean.getBooleanProperty(), true, "Set property failed (1)");
955 
956         bean.setBooleanProperty(false);
957         utilsTwo.setProperty(bean, "booleanProperty", "true");
958         assertEquals(bean.getBooleanProperty(), true, "Set property failed (2)");
959 
960         // now change the registered conversion
961 
962         utilsOne.getConvertUtils().register(new ThrowExceptionConverter(), Boolean.TYPE);
963         bean.setBooleanProperty(false);
964         assertThrows(PassTestException.class, () -> utilsOne.setProperty(bean, "booleanProperty", "true"));
965 
966         // make sure that this conversion has no been registered in the other instance
967         bean.setBooleanProperty(false);
968         utilsTwo.setProperty(bean, "booleanProperty", "true");
969         assertEquals(bean.getBooleanProperty(), true, "Set property failed (3)");
970     }
971 
972     /**
973      * Test setting a value out of a mapped Map
974      */
975     @Test
976     public void testSetMappedMap() throws Exception {
977         final TestBean bean = new TestBean();
978         final Map<String, Object> map = new HashMap<>();
979         map.put("sub-key-1", "sub-value-1");
980         map.put("sub-key-2", "sub-value-2");
981         map.put("sub-key-3", "sub-value-3");
982         bean.getMapProperty().put("mappedMap", map);
983 
984         assertEquals("sub-value-3", ((Map<?, ?>) bean.getMapProperty().get("mappedMap")).get("sub-key-3"), "BEFORE");
985         BeanUtils.setProperty(bean, "mapProperty(mappedMap)(sub-key-3)", "SUB-KEY-3-UPDATED");
986         assertEquals("SUB-KEY-3-UPDATED", ((Map<?, ?>) bean.getMapProperty().get("mappedMap")).get("sub-key-3"), "AFTER");
987     }
988 
989     /**
990      * Test narrowing and widening conversions on byte.
991      */
992     @Test
993     public void testSetPropertyByte() throws Exception {
994 
995         BeanUtils.setProperty(bean, "byteProperty", Byte.valueOf((byte) 123));
996         assertEquals((byte) 123, bean.getByteProperty());
997         /*
998          * BeanUtils.setProperty(bean, "byteProperty", new Double((double) 123)); assertEquals((byte) 123, bean.getByteProperty()); BeanUtils.setProperty(bean,
999          * "byteProperty", new Float((float) 123)); assertEquals((byte) 123, bean.getByteProperty());
1000          */
1001         BeanUtils.setProperty(bean, "byteProperty", Integer.valueOf(123));
1002         assertEquals((byte) 123, bean.getByteProperty());
1003         BeanUtils.setProperty(bean, "byteProperty", Long.valueOf(123));
1004         assertEquals((byte) 123, bean.getByteProperty());
1005         BeanUtils.setProperty(bean, "byteProperty", Short.valueOf((short) 123));
1006         assertEquals((byte) 123, bean.getByteProperty());
1007 
1008     }
1009 
1010     /**
1011      * Test {@code setProperty()} conversion.
1012      */
1013     @Test
1014     public void testSetPropertyConvert() throws Exception {
1015         BeanUtils.setProperty(bean, "dateProperty", testCalendar);
1016         assertEquals(testUtilDate, bean.getDateProperty(), "Calendar --> java.util.Date");
1017     }
1018 
1019     /**
1020      * Test {@code setProperty()} converting from a String.
1021      */
1022     @Test
1023     public void testSetPropertyConvertFromString() throws Exception {
1024         BeanUtils.setProperty(bean, "dateProperty", testStringDate);
1025         assertEquals(testUtilDate, bean.getDateProperty(), "String --> java.util.Date");
1026     }
1027 
1028     /**
1029      * Test {@code setProperty()} converting to a String.
1030      */
1031     @Test
1032     public void testSetPropertyConvertToString() throws Exception {
1033         BeanUtils.setProperty(bean, "stringProperty", testUtilDate);
1034         assertEquals(testStringDate, bean.getStringProperty(), "java.util.Date --> String");
1035     }
1036 
1037     /**
1038      * Test {@code setProperty()} converting to a String array.
1039      */
1040     @Test
1041     public void testSetPropertyConvertToStringArray() throws Exception {
1042         bean.setStringArray(null);
1043         BeanUtils.setProperty(bean, "stringArray", new java.util.Date[] { testUtilDate });
1044         assertEquals(1, bean.getStringArray().length, "java.util.Date[] --> String[] length");
1045         assertEquals(testStringDate, bean.getStringArray()[0], "java.util.Date[] --> String[] value ");
1046     }
1047 
1048     /**
1049      * Test {@code setProperty()} converting to a String on indexed property
1050      */
1051     @Test
1052     public void testSetPropertyConvertToStringIndexed() throws Exception {
1053         bean.setStringArray(new String[1]);
1054         BeanUtils.setProperty(bean, "stringArray[0]", testUtilDate);
1055         assertEquals(testStringDate, bean.getStringArray()[0], "java.util.Date --> String[]");
1056     }
1057 
1058     /**
1059      * Test narrowing and widening conversions on double.
1060      */
1061     @Test
1062     public void testSetPropertyDouble() throws Exception {
1063 
1064         BeanUtils.setProperty(bean, "doubleProperty", Byte.valueOf((byte) 123));
1065         assertEquals(123, bean.getDoubleProperty(), 0.005);
1066         BeanUtils.setProperty(bean, "doubleProperty", Double.valueOf(123));
1067         assertEquals(123, bean.getDoubleProperty(), 0.005);
1068         BeanUtils.setProperty(bean, "doubleProperty", Float.valueOf(123));
1069         assertEquals(123, bean.getDoubleProperty(), 0.005);
1070         BeanUtils.setProperty(bean, "doubleProperty", Integer.valueOf(123));
1071         assertEquals(123, bean.getDoubleProperty(), 0.005);
1072         BeanUtils.setProperty(bean, "doubleProperty", Long.valueOf(123));
1073         assertEquals(123, bean.getDoubleProperty(), 0.005);
1074         BeanUtils.setProperty(bean, "doubleProperty", Short.valueOf((short) 123));
1075         assertEquals(123, bean.getDoubleProperty(), 0.005);
1076 
1077     }
1078 
1079     /**
1080      * Test narrowing and widening conversions on float.
1081      */
1082     @Test
1083     public void testSetPropertyFloat() throws Exception {
1084 
1085         BeanUtils.setProperty(bean, "floatProperty", Byte.valueOf((byte) 123));
1086         assertEquals(123, bean.getFloatProperty(), 0.005);
1087         BeanUtils.setProperty(bean, "floatProperty", Double.valueOf(123));
1088         assertEquals(123, bean.getFloatProperty(), 0.005);
1089         BeanUtils.setProperty(bean, "floatProperty", Float.valueOf(123));
1090         assertEquals(123, bean.getFloatProperty(), 0.005);
1091         BeanUtils.setProperty(bean, "floatProperty", Integer.valueOf(123));
1092         assertEquals(123, bean.getFloatProperty(), 0.005);
1093         BeanUtils.setProperty(bean, "floatProperty", Long.valueOf(123));
1094         assertEquals(123, bean.getFloatProperty(), 0.005);
1095         BeanUtils.setProperty(bean, "floatProperty", Short.valueOf((short) 123));
1096         assertEquals(123, bean.getFloatProperty(), 0.005);
1097 
1098     }
1099 
1100     /**
1101      * Test narrowing and widening conversions on int.
1102      */
1103     @Test
1104     public void testSetPropertyInteger() throws Exception {
1105 
1106         BeanUtils.setProperty(bean, "longProperty", Byte.valueOf((byte) 123));
1107         assertEquals(123, bean.getIntProperty());
1108         /*
1109          * BeanUtils.setProperty(bean, "longProperty", new Double((double) 123)); assertEquals((int) 123, bean.getIntProperty()); BeanUtils.setProperty(bean,
1110          * "longProperty", new Float((float) 123)); assertEquals((int) 123, bean.getIntProperty());
1111          */
1112         BeanUtils.setProperty(bean, "longProperty", Integer.valueOf(123));
1113         assertEquals(123, bean.getIntProperty());
1114         BeanUtils.setProperty(bean, "longProperty", Long.valueOf(123));
1115         assertEquals(123, bean.getIntProperty());
1116         BeanUtils.setProperty(bean, "longProperty", Short.valueOf((short) 123));
1117         assertEquals(123, bean.getIntProperty());
1118 
1119     }
1120 
1121     /**
1122      * Test narrowing and widening conversions on long.
1123      */
1124     @Test
1125     public void testSetPropertyLong() throws Exception {
1126 
1127         BeanUtils.setProperty(bean, "longProperty", Byte.valueOf((byte) 123));
1128         assertEquals(123, bean.getLongProperty());
1129         /*
1130          * BeanUtils.setProperty(bean, "longProperty", new Double((double) 123)); assertEquals((long) 123, bean.getLongProperty()); BeanUtils.setProperty(bean,
1131          * "longProperty", new Float((float) 123)); assertEquals((long) 123, bean.getLongProperty());
1132          */
1133         BeanUtils.setProperty(bean, "longProperty", Integer.valueOf(123));
1134         assertEquals(123, bean.getLongProperty());
1135         BeanUtils.setProperty(bean, "longProperty", Long.valueOf(123));
1136         assertEquals(123, bean.getLongProperty());
1137         BeanUtils.setProperty(bean, "longProperty", Short.valueOf((short) 123));
1138         assertEquals(123, bean.getLongProperty());
1139 
1140     }
1141 
1142     /**
1143      * Test setting a null property value.
1144      */
1145     @Test
1146     public void testSetPropertyNull() throws Exception {
1147 
1148         bean.setNullProperty("non-null value");
1149         BeanUtils.setProperty(bean, "nullProperty", null);
1150         assertNull(bean.getNullProperty(), "nullProperty is null");
1151 
1152     }
1153 
1154     /**
1155      * Test calling setProperty() with null property values.
1156      */
1157     @Test
1158     public void testSetPropertyNullValues() throws Exception {
1159 
1160         Object oldValue;
1161         Object newValue;
1162 
1163         // Scalar value into array
1164         oldValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
1165         BeanUtils.setProperty(bean, "stringArray", null);
1166         newValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
1167         assertNotNull(newValue, "stringArray is not null");
1168         assertInstanceOf(String[].class, newValue, "stringArray of correct type");
1169         assertEquals(1, ((String[]) newValue).length, "stringArray length");
1170         PropertyUtils.setProperty(bean, "stringArray", oldValue);
1171 
1172         // Indexed value into array
1173         oldValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
1174         BeanUtils.setProperty(bean, "stringArray[2]", null);
1175         newValue = PropertyUtils.getSimpleProperty(bean, "stringArray");
1176         assertNotNull(newValue, "stringArray is not null");
1177         assertInstanceOf(String[].class, newValue, "stringArray of correct type");
1178         assertEquals(5, ((String[]) newValue).length, "stringArray length");
1179         assertNull(((String[]) newValue)[2], "stringArray[2] is null");
1180         PropertyUtils.setProperty(bean, "stringArray", oldValue);
1181 
1182         // Value into scalar
1183         BeanUtils.setProperty(bean, "stringProperty", null);
1184         assertNull(BeanUtils.getProperty(bean, "stringProperty"), "stringProperty is now null");
1185 
1186     }
1187 
1188     /**
1189      * Test converting to and from primitive wrapper types.
1190      */
1191     @Test
1192     public void testSetPropertyOnPrimitiveWrappers() throws Exception {
1193 
1194         BeanUtils.setProperty(bean, "intProperty", Integer.valueOf(1));
1195         assertEquals(1, bean.getIntProperty());
1196         BeanUtils.setProperty(bean, "stringProperty", Integer.valueOf(1));
1197         assertEquals(1, Integer.parseInt(bean.getStringProperty()));
1198 
1199     }
1200 
1201     /**
1202      * Test narrowing and widening conversions on short.
1203      */
1204     @Test
1205     public void testSetPropertyShort() throws Exception {
1206 
1207         BeanUtils.setProperty(bean, "shortProperty", Byte.valueOf((byte) 123));
1208         assertEquals((short) 123, bean.getShortProperty());
1209         /*
1210          * BeanUtils.setProperty(bean, "shortProperty", new Double((double) 123)); assertEquals((short) 123, bean.getShortProperty());
1211          * BeanUtils.setProperty(bean, "shortProperty", new Float((float) 123)); assertEquals((short) 123, bean.getShortProperty());
1212          */
1213         BeanUtils.setProperty(bean, "shortProperty", Integer.valueOf(123));
1214         assertEquals((short) 123, bean.getShortProperty());
1215         BeanUtils.setProperty(bean, "shortProperty", Long.valueOf(123));
1216         assertEquals((short) 123, bean.getShortProperty());
1217         BeanUtils.setProperty(bean, "shortProperty", Short.valueOf((short) 123));
1218         assertEquals((short) 123, bean.getShortProperty());
1219 
1220     }
1221 
1222     /**
1223      * Test setting a String value to a String array property
1224      */
1225     @Test
1226     public void testSetPropertyStringToArray() throws Exception {
1227         BeanUtils.setProperty(bean, "stringArray", "ABC,DEF,GHI");
1228         final String[] strArray = bean.getStringArray();
1229         assertEquals(3, strArray.length, "length");
1230         assertEquals("ABC", strArray[0], "value[0]");
1231         assertEquals("DEF", strArray[1], "value[1]");
1232         assertEquals("GHI", strArray[2], "value[2]");
1233 
1234         BeanUtils.setProperty(bean, "intArray", "0, 10, 20, 30, 40");
1235         final int[] intArray = bean.getIntArray();
1236         assertEquals(5, intArray.length, "length");
1237         assertEquals(0, intArray[0], "value[0]");
1238         assertEquals(10, intArray[1], "value[1]");
1239         assertEquals(20, intArray[2], "value[2]");
1240         assertEquals(30, intArray[3], "value[3]");
1241         assertEquals(40, intArray[4], "value[4]");
1242     }
1243 
1244     /**
1245      * Test setting a new value to a write-only property, with and without conversions.
1246      */
1247     @Test
1248     public void testSetPropertyWriteOnly() throws Exception {
1249 
1250         bean.setWriteOnlyProperty("Original value");
1251 
1252         // No conversion required
1253         BeanUtils.setProperty(bean, "writeOnlyProperty", "New value");
1254         assertEquals("New value", bean.getWriteOnlyPropertyValue());
1255 
1256         // Integer->String conversion required
1257         BeanUtils.setProperty(bean, "writeOnlyProperty", Integer.valueOf(123));
1258         assertEquals("123", bean.getWriteOnlyPropertyValue());
1259 
1260     }
1261 
1262     /**
1263      * Throw an exception with the specified message.
1264      */
1265     private void throwException(final String msg) throws Throwable {
1266         throw new Exception(msg);
1267     }
1268 }