Source code: org/apache/commons/beanutils/PropertyUtilsTestCase.java
1 /*
2 * Copyright 2001-2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18 package org.apache.commons.beanutils;
19
20
21 import java.beans.PropertyDescriptor;
22 import java.lang.reflect.InvocationTargetException;
23 import java.lang.reflect.Method;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.apache.commons.beanutils.priv.PrivateBeanFactory;
29 import org.apache.commons.beanutils.priv.PrivateDirect;
30
31 import junit.framework.TestCase;
32 import junit.framework.Test;
33 import junit.framework.TestSuite;
34
35
36 /**
37 * <p>Test Case for the PropertyUtils class. The majority of these tests use
38 * instances of the TestBean class, so be sure to update the tests if you
39 * change the characteristics of that class.</p>
40 *
41 * <p>So far, this test case has tests for the following methods of the
42 * <code>PropertyUtils</code> class:</p>
43 * <ul>
44 * <li>getIndexedProperty(Object,String)</li>
45 * <li>getIndexedProperty(Object,String,int)</li>
46 * <li>getMappedProperty(Object,String)</li>
47 * <li>getMappedProperty(Object,String,String</li>
48 * <li>getNestedProperty(Object,String)</li>
49 * <li>getPropertyDescriptor(Object,String)</li>
50 * <li>getPropertyDescriptors(Object)</li>
51 * <li>getPropertyType(Object,String)</li>
52 * <li>getSimpleProperty(Object,String)</li>
53 * <li>setIndexedProperty(Object,String,Object)</li>
54 * <li>setIndexedProperty(Object,String,String,Object)</li>
55 * <li>setMappedProperty(Object,String,Object)</li>
56 * <li>setMappedProperty(Object,String,String,Object)</li>
57 * <li>setNestedProperty(Object,String,Object)</li>
58 * <li>setSimpleProperty(Object,String,Object)</li>
59 * </ul>
60 *
61 * @author Craig R. McClanahan
62 * @author Jan Sorensen
63 * @version $Revision: 1.34 $ $Date: 2004/02/28 13:18:36 $
64 */
65
66 public class PropertyUtilsTestCase extends TestCase {
67
68
69 // ---------------------------------------------------- Instance Variables
70
71
72 /**
73 * The fully qualified class name of our private directly
74 * implemented interface.
75 */
76 private static final String PRIVATE_DIRECT_CLASS =
77 "org.apache.commons.beanutils.priv.PrivateDirect";
78
79
80 /**
81 * The fully qualified class name of our private indirectly
82 * implemented interface.
83 */
84 private static final String PRIVATE_INDIRECT_CLASS =
85 "org.apache.commons.beanutils.priv.PrivateIndirect";
86
87
88 /**
89 * The fully qualified class name of our test bean class.
90 */
91 private static final String TEST_BEAN_CLASS =
92 "org.apache.commons.beanutils.TestBean";
93
94
95 /**
96 * The basic test bean for each test.
97 */
98 protected TestBean bean = null;
99
100
101 /**
102 * The "package private subclass" test bean for each test.
103 */
104 protected TestBeanPackageSubclass beanPackageSubclass = null;
105
106
107 /**
108 * The test bean for private access tests.
109 */
110 protected PrivateDirect beanPrivate = null;
111
112
113 /**
114 * The test bean for private access tests of subclasses.
115 */
116 protected PrivateDirect beanPrivateSubclass = null;
117
118
119 /**
120 * The "public subclass" test bean for each test.
121 */
122 protected TestBeanPublicSubclass beanPublicSubclass = null;
123
124
125 /**
126 * The set of properties that should be described.
127 */
128 protected String describes[] =
129 { "booleanProperty",
130 "booleanSecond",
131 "doubleProperty",
132 "floatProperty",
133 "intArray",
134 // "intIndexed",
135 "intProperty",
136 "listIndexed",
137 "longProperty",
138 // "mappedObjects",
139 // "mappedProperty",
140 // "mappedIntProperty",
141 "nested",
142 "nullProperty",
143 // "readOnlyProperty",
144 "shortProperty",
145 "stringArray",
146 // "stringIndexed",
147 "stringProperty"
148 };
149
150
151 /**
152 * The set of property names we expect to have returned when calling
153 * <code>getPropertyDescriptors()</code>. You should update this list
154 * when new properties are added to TestBean.
155 */
156 protected final static String[] properties = {
157 "booleanProperty",
158 "booleanSecond",
159 "doubleProperty",
160 "dupProperty",
161 "floatProperty",
162 "intArray",
163 "intIndexed",
164 "intProperty",
165 "listIndexed",
166 "longProperty",
167 "nested",
168 "nullProperty",
169 "readOnlyProperty",
170 "shortProperty",
171 "stringArray",
172 "stringIndexed",
173 "stringProperty",
174 "writeOnlyProperty",
175 };
176
177
178 // ---------------------------------------------------------- Constructors
179
180
181 /**
182 * Construct a new instance of this test case.
183 *
184 * @param name Name of the test case
185 */
186 public PropertyUtilsTestCase(String name) {
187
188 super(name);
189
190 }
191
192
193 // -------------------------------------------------- Overall Test Methods
194
195
196 /**
197 * Set up instance variables required by this test case.
198 */
199 public void setUp() {
200
201 bean = new TestBean();
202 beanPackageSubclass = new TestBeanPackageSubclass();
203 beanPrivate = PrivateBeanFactory.create();
204 beanPrivateSubclass = PrivateBeanFactory.createSubclass();
205 beanPublicSubclass = new TestBeanPublicSubclass();
206
207 }
208
209
210 /**
211 * Return the tests included in this test suite.
212 */
213 public static Test suite() {
214
215 return (new TestSuite(PropertyUtilsTestCase.class));
216
217 }
218
219
220 /**
221 * Tear down instance variables required by this test case.
222 */
223 public void tearDown() {
224
225 bean = null;
226 beanPackageSubclass = null;
227 beanPrivate = null;
228 beanPrivateSubclass = null;
229 beanPublicSubclass = null;
230
231 }
232
233
234
235 // ------------------------------------------------ Individual Test Methods
236
237
238 /**
239 * Test copyProperties() when the origin is a a <code>Map</code>.
240 */
241 public void testCopyPropertiesMap() {
242
243 Map map = new HashMap();
244 map.put("booleanProperty", Boolean.FALSE);
245 map.put("doubleProperty", new Double(333.0));
246 map.put("dupProperty", new String[] { "New 0", "New 1", "New 2" });
247 map.put("floatProperty", new Float((float) 222.0));
248 map.put("intArray", new int[] { 0, 100, 200 });
249 map.put("intProperty", new Integer(111));
250 map.put("longProperty", new Long(444));
251 map.put("shortProperty", new Short((short) 555));
252 map.put("stringProperty", "New String Property");
253
254 try {
255 PropertyUtils.copyProperties(bean, map);
256 } catch (Throwable t) {
257 fail("Threw " + t.toString());
258 }
259
260 // Scalar properties
261 assertEquals("booleanProperty", false,
262 bean.getBooleanProperty());
263 assertEquals("doubleProperty", 333.0,
264 bean.getDoubleProperty(), 0.005);
265 assertEquals("floatProperty", (float) 222.0,
266 bean.getFloatProperty(), (float) 0.005);
267 assertEquals("intProperty", 111,
268 bean.getIntProperty());
269 assertEquals("longProperty", (long) 444,
270 bean.getLongProperty());
271 assertEquals("shortProperty", (short) 555,
272 bean.getShortProperty());
273 assertEquals("stringProperty", "New String Property",
274 bean.getStringProperty());
275
276 // Indexed Properties
277 String dupProperty[] = bean.getDupProperty();
278 assertNotNull("dupProperty present", dupProperty);
279 assertEquals("dupProperty length", 3, dupProperty.length);
280 assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
281 assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
282 assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
283 int intArray[] = bean.getIntArray();
284 assertNotNull("intArray present", intArray);
285 assertEquals("intArray length", 3, intArray.length);
286 assertEquals("intArray[0]", 0, intArray[0]);
287 assertEquals("intArray[1]", 100, intArray[1]);
288 assertEquals("intArray[2]", 200, intArray[2]);
289
290 }
291
292
293 /**
294 * Test the describe() method.
295 */
296 public void testDescribe() {
297
298 Map map = null;
299 try {
300 map = PropertyUtils.describe(bean);
301 } catch (Exception e) {
302 fail("Threw exception " + e);
303 }
304
305 // Verify existence of all the properties that should be present
306 for (int i = 0; i < describes.length; i++) {
307 assertTrue("Property '" + describes[i] + "' is present",
308 map.containsKey(describes[i]));
309 }
310 assertTrue("Property 'writeOnlyProperty' is not present",
311 !map.containsKey("writeOnlyProperty"));
312
313 // Verify the values of scalar properties
314 assertEquals("Value of 'booleanProperty'",
315 Boolean.TRUE,
316 (Boolean) map.get("booleanProperty"));
317 assertEquals("Value of 'doubleProperty'",
318 new Double(321.0),
319 (Double) map.get("doubleProperty"));
320 assertEquals("Value of 'floatProperty'",
321 new Float((float) 123.0),
322 (Float) map.get("floatProperty"));
323 assertEquals("Value of 'intProperty'",
324 new Integer(123),
325 (Integer) map.get("intProperty"));
326 assertEquals("Value of 'longProperty'",
327 new Long(321),
328 (Long) map.get("longProperty"));
329 assertEquals("Value of 'shortProperty'",
330 new Short((short) 987),
331 (Short) map.get("shortProperty"));
332 assertEquals("Value of 'stringProperty'",
333 "This is a string",
334 (String) map.get("stringProperty"));
335
336 }
337
338
339 /**
340 * Corner cases on getPropertyDescriptor invalid arguments.
341 */
342 public void testGetDescriptorArguments() {
343
344 try {
345 PropertyUtils.getPropertyDescriptor(null, "stringProperty");
346 fail("Should throw IllegalArgumentException 1");
347 } catch (IllegalArgumentException e) {
348 ; // Expected response
349 } catch (Throwable t) {
350 fail("Threw " + t + " instead of IllegalArgumentException 1");
351 }
352
353 try {
354 PropertyUtils.getPropertyDescriptor(bean, null);
355 fail("Should throw IllegalArgumentException 2");
356 } catch (IllegalArgumentException e) {
357 ; // Expected response
358 } catch (Throwable t) {
359 fail("Threw " + t + " instead of IllegalArgumentException 2");
360 }
361
362 }
363
364
365 /**
366 * Positive getPropertyDescriptor on property <code>booleanProperty</code>.
367 */
368 public void testGetDescriptorBoolean() {
369
370 testGetDescriptorBase("booleanProperty", "getBooleanProperty",
371 "setBooleanProperty");
372
373 }
374
375
376 /**
377 * Positive getPropertyDescriptor on property <code>doubleProperty</code>.
378 */
379 public void testGetDescriptorDouble() {
380
381 testGetDescriptorBase("doubleProperty", "getDoubleProperty",
382 "setDoubleProperty");
383
384 }
385
386
387 /**
388 * Positive getPropertyDescriptor on property <code>floatProperty</code>.
389 */
390 public void testGetDescriptorFloat() {
391
392 testGetDescriptorBase("floatProperty", "getFloatProperty",
393 "setFloatProperty");
394
395 }
396
397
398 /**
399 * Positive getPropertyDescriptor on property <code>intProperty</code>.
400 */
401 public void testGetDescriptorInt() {
402
403 testGetDescriptorBase("intProperty", "getIntProperty",
404 "setIntProperty");
405
406 }
407
408
409 /**
410 * <p>Negative tests on an invalid property with two different boolean
411 * getters (which is fine, according to the JavaBeans spec) but a
412 * String setter instead of a boolean setter.</p>
413 *
414 * <p>Although one could logically argue that this combination of method
415 * signatures should not identify a property at all, there is a sentence
416 * in Section 8.3.1 making it clear that the behavior tested for here
417 * is correct: "If we find only one of these methods, then we regard
418 * it as defining either a read-only or write-only property called
419 * <em><property-name></em>.</p>
420 */
421 public void testGetDescriptorInvalidBoolean() throws Exception {
422
423 PropertyDescriptor pd =
424 PropertyUtils.getPropertyDescriptor(bean, "invalidBoolean");
425 assertNotNull("invalidBoolean is a property", pd);
426 assertNotNull("invalidBoolean has a getter method",
427 pd.getReadMethod());
428 assertNull("invalidBoolean has no write method",
429 pd.getWriteMethod());
430 assertTrue("invalidBoolean getter method is isInvalidBoolean",
431 "isInvalidBoolean".equals(pd.getReadMethod().getName()));
432
433 }
434
435
436 /**
437 * Positive getPropertyDescriptor on property <code>longProperty</code>.
438 */
439 public void testGetDescriptorLong() {
440
441 testGetDescriptorBase("longProperty", "getLongProperty",
442 "setLongProperty");
443
444 }
445
446
447 /**
448 * Positive getPropertyDescriptor on property
449 * <code>readOnlyProperty</code>.
450 */
451 public void testGetDescriptorReadOnly() {
452
453 testGetDescriptorBase("readOnlyProperty", "getReadOnlyProperty",
454 null);
455
456 }
457
458
459 /**
460 * Positive getPropertyDescriptor on property <code>booleanSecond</code>
461 * that uses an "is" method as the getter.
462 */
463 public void testGetDescriptorSecond() {
464
465 testGetDescriptorBase("booleanSecond", "isBooleanSecond",
466 "setBooleanSecond");
467
468 }
469
470
471 /**
472 * Positive getPropertyDescriptor on property <code>shortProperty</code>.
473 */
474 public void testGetDescriptorShort() {
475
476 testGetDescriptorBase("shortProperty", "getShortProperty",
477 "setShortProperty");
478
479 }
480
481
482 /**
483 * Positive getPropertyDescriptor on property <code>stringProperty</code>.
484 */
485 public void testGetDescriptorString() {
486
487 testGetDescriptorBase("stringProperty", "getStringProperty",
488 "setStringProperty");
489
490 }
491
492
493 /**
494 * Negative getPropertyDescriptor on property <code>unknown</code>.
495 */
496 public void testGetDescriptorUnknown() {
497
498 testGetDescriptorBase("unknown", null, null);
499
500 }
501
502
503 /**
504 * Positive getPropertyDescriptor on property
505 * <code>writeOnlyProperty</code>.
506 */
507 public void testGetDescriptorWriteOnly() {
508
509 testGetDescriptorBase("writeOnlyProperty", null,
510 "setWriteOnlyProperty");
511
512 }
513
514
515 /**
516 * Positive test for getPropertyDescriptors(). Each property name
517 * listed in <code>properties</code> should be returned exactly once.
518 */
519 public void testGetDescriptors() {
520
521 PropertyDescriptor pd[] =
522 PropertyUtils.getPropertyDescriptors(bean);
523 assertNotNull("Got descriptors", pd);
524 int count[] = new int[properties.length];
525 for (int i = 0; i < pd.length; i++) {
526 String name = pd[i].getName();
527 for (int j = 0; j < properties.length; j++) {
528 if (name.equals(properties[j]))
529 count[j]++;
530 }
531 }
532 for (int j = 0; j < properties.length; j++) {
533 if (count[j] < 0)
534 fail("Missing property " + properties[j]);
535 else if (count[j] > 1)
536 fail("Duplicate property " + properties[j]);
537 }
538
539 }
540
541
542 /**
543 * Corner cases on getPropertyDescriptors invalid arguments.
544 */
545 public void testGetDescriptorsArguments() {
546
547 try {
548 PropertyUtils.getPropertyDescriptors(null);
549 fail("Should throw IllegalArgumentException");
550 } catch (IllegalArgumentException e) {
551 ; // Expected response
552 } catch (Throwable t) {
553 fail("Threw " + t + " instead of IllegalArgumentException");
554 }
555
556 }
557
558
559 /**
560 * Corner cases on getIndexedProperty invalid arguments.
561 */
562 public void testGetIndexedArguments() {
563
564 // Use explicit index argument
565
566 try {
567 PropertyUtils.getIndexedProperty(null, "intArray", 0);
568 fail("Should throw IllegalArgumentException 1");
569 } catch (IllegalArgumentException e) {
570 ; // Expected response
571 } catch (Throwable t) {
572 fail("Threw " + t + " instead of IllegalArgumentException 1");
573 }
574
575 try {
576 PropertyUtils.getIndexedProperty(bean, null, 0);
577 fail("Should throw IllegalArgumentException 2");
578 } catch (IllegalArgumentException e) {
579 ; // Expected response
580 } catch (Throwable t) {
581 fail("Threw " + t + " instead of IllegalArgumentException 2");
582 }
583
584 // Use index expression
585
586 try {
587 PropertyUtils.getIndexedProperty(null,
588 "intArray[0]");
589 fail("Should throw IllegalArgumentException 3");
590 } catch (IllegalArgumentException e) {
591 ; // Expected response
592 } catch (Throwable t) {
593 fail("Threw " + t + " instead of IllegalArgumentException 3");
594 }
595
596 try {
597 PropertyUtils.getIndexedProperty(bean, "[0]");
598 fail("Should throw NoSuchMethodException 4");
599 } catch (NoSuchMethodException e) {
600 ; // Expected response
601 } catch (Throwable t) {
602 fail("Threw " + t + " instead of NoSuchMethodException 4");
603 }
604
605 try {
606 PropertyUtils.getIndexedProperty(bean, "intArray");
607 fail("Should throw IllegalArgumentException 5");
608 } catch (IllegalArgumentException e) {
609 ; // Expected response
610 } catch (Throwable t) {
611 fail("Threw " + t + " instead of IllegalArgumentException 5");
612 }
613
614 // Use explicit index argument
615
616 try {
617 PropertyUtils.getIndexedProperty(null, "intIndexed", 0);
618 fail("Should throw IllegalArgumentException 1");
619 } catch (IllegalArgumentException e) {
620 ; // Expected response
621 } catch (Throwable t) {
622 fail("Threw " + t + " instead of IllegalArgumentException 1");
623 }
624
625 try {
626 PropertyUtils.getIndexedProperty(bean, null, 0);
627 fail("Should throw IllegalArgumentException 2");
628 } catch (IllegalArgumentException e) {
629 ; // Expected response
630 } catch (Throwable t) {
631 fail("Threw " + t + " instead of IllegalArgumentException 2");
632 }
633
634 // Use index expression
635
636 try {
637 PropertyUtils.getIndexedProperty(null,
638 "intIndexed[0]");
639 fail("Should throw IllegalArgumentException 3");
640 } catch (IllegalArgumentException e) {
641 ; // Expected response
642 } catch (Throwable t) {
643 fail("Threw " + t + " instead of IllegalArgumentException 3");
644 }
645
646 try {
647 PropertyUtils.getIndexedProperty(bean, "[0]");
648 fail("Should throw NoSuchMethodException 4");
649 } catch (NoSuchMethodException e) {
650 ; // Expected response
651 } catch (Throwable t) {
652 fail("Threw " + t + " instead of NoSuchMethodException 4");
653 }
654
655 try {
656 PropertyUtils.getIndexedProperty(bean, "intIndexed");
657 fail("Should throw IllegalArgumentException 5");
658 } catch (IllegalArgumentException e) {
659 ; // Expected response
660 } catch (Throwable t) {
661 fail("Threw " + t + " instead of IllegalArgumentException 5");
662 }
663
664 }
665
666
667 /**
668 * Positive and negative tests on getIndexedProperty valid arguments.
669 */
670 public void testGetIndexedValues() {
671
672 Object value = null;
673
674 // Use explicit key argument
675
676 for (int i = 0; i < 5; i++) {
677
678 try {
679 value = PropertyUtils.getIndexedProperty
680 (bean, "dupProperty", i);
681 assertNotNull("dupProperty returned value " + i, value);
682 assertTrue("dupProperty returned String " + i,
683 value instanceof String);
684 assertEquals("dupProperty returned correct " + i,
685 "Dup " + i,
686 (String) value);
687 } catch (Throwable t) {
688 fail("dupProperty " + i + " threw " + t);
689 }
690
691 try {
692 value =
693 PropertyUtils.getIndexedProperty(bean, "intArray", i);
694 assertNotNull("intArray returned value " + i, value);
695 assertTrue("intArray returned Integer " + i,
696 value instanceof Integer);
697 assertEquals("intArray returned correct " + i, i * 10,
698 ((Integer) value).intValue());
699 } catch (Throwable t) {
700 fail("intArray " + i + " threw " + t);
701 }
702
703 try {
704 value =
705 PropertyUtils.getIndexedProperty(bean, "intIndexed", i);
706 assertNotNull("intIndexed returned value " + i, value);
707 assertTrue("intIndexed returned Integer " + i,
708 value instanceof Integer);
709 assertEquals("intIndexed returned correct " + i, i * 10,
710 ((Integer) value).intValue());
711 } catch (Throwable t) {
712 fail("intIndexed " + i + " threw " + t);
713 }
714
715 try {
716 value =
717 PropertyUtils.getIndexedProperty(bean, "listIndexed", i);
718 assertNotNull("listIndexed returned value " + i, value);
719 assertTrue("list returned String " + i,
720 value instanceof String);
721 assertEquals("listIndexed returned correct " + i,
722 "String " + i, (String) value);
723 } catch (Throwable t) {
724 fail("listIndexed " + i + " threw " + t);
725 }
726
727 try {
728 value =
729 PropertyUtils.getIndexedProperty(bean, "stringArray", i);
730 assertNotNull("stringArray returned value " + i, value);
731 assertTrue("stringArray returned String " + i,
732 value instanceof String);
733 assertEquals("stringArray returned correct " + i,
734 "String " + i, (String) value);
735 } catch (Throwable t) {
736 fail("stringArray " + i + " threw " + t);
737 }
738
739 try {
740 value =
741 PropertyUtils.getIndexedProperty(bean, "stringIndexed", i);
742 assertNotNull("stringIndexed returned value " + i, value);
743 assertTrue("stringIndexed returned String " + i,
744 value instanceof String);
745 assertEquals("stringIndexed returned correct " + i,
746 "String " + i, (String) value);
747 } catch (Throwable t) {
748 fail("stringIndexed " + i + " threw " + t);
749 }
750
751 }
752
753 // Use key expression
754
755 for (int i = 0; i < 5; i++) {
756
757 try {
758 value = PropertyUtils.getIndexedProperty
759 (bean, "dupProperty[" + i + "]");
760 assertNotNull("dupProperty returned value " + i, value);
761 assertTrue("dupProperty returned String " + i,
762 value instanceof String);
763 assertEquals("dupProperty returned correct " + i,
764 "Dup " + i,
765 (String) value);
766 } catch (Throwable t) {
767 fail("dupProperty " + i + " threw " + t);
768 }
769
770 try {
771 value =
772 PropertyUtils.getIndexedProperty(bean,
773 "intArray[" + i + "]");
774 assertNotNull("intArray returned value " + i, value);
775 assertTrue("intArray returned Integer " + i,
776 value instanceof Integer);
777 assertEquals("intArray returned correct " + i, i * 10,
778 ((Integer) value).intValue());
779 } catch (Throwable t) {
780 fail("intArray " + i + " threw " + t);
781 }
782
783 try {
784 value =
785 PropertyUtils.getIndexedProperty(bean,
786 "intIndexed[" + i + "]");
787 assertNotNull("intIndexed returned value " + i, value);
788 assertTrue("intIndexed returned Integer " + i,
789 value instanceof Integer);
790 assertEquals("intIndexed returned correct " + i, i * 10,
791 ((Integer) value).intValue());
792 } catch (Throwable t) {
793 fail("intIndexed " + i + " threw " + t);
794 }
795
796 try {
797 value =
798 PropertyUtils.getIndexedProperty(bean,
799 "listIndexed[" + i + "]");
800 assertNotNull("listIndexed returned value " + i, value);
801 assertTrue("listIndexed returned String " + i,
802 value instanceof String);
803 assertEquals("listIndexed returned correct " + i,
804 "String " + i, (String) value);
805 } catch (Throwable t) {
806 fail("listIndexed " + i + " threw " + t);
807 }
808
809 try {
810 value =
811 PropertyUtils.getIndexedProperty(bean,
812 "stringArray[" + i + "]");
813 assertNotNull("stringArray returned value " + i, value);
814 assertTrue("stringArray returned String " + i,
815 value instanceof String);
816 assertEquals("stringArray returned correct " + i,
817 "String " + i, (String) value);
818 } catch (Throwable t) {
819 fail("stringArray " + i + " threw " + t);
820 }
821
822 try {
823 value =
824 PropertyUtils.getIndexedProperty(bean,
825 "stringIndexed[" + i + "]");
826 assertNotNull("stringIndexed returned value " + i, value);
827 assertTrue("stringIndexed returned String " + i,
828 value instanceof String);
829 assertEquals("stringIndexed returned correct " + i,
830 "String " + i, (String) value);
831 } catch (Throwable t) {
832 fail("stringIndexed " + i + " threw " + t);
833 }
834
835 }
836
837 // Index out of bounds tests
838
839 try {
840 value =
841 PropertyUtils.getIndexedProperty(bean,
842 "dupProperty", -1);
843 fail("Should have thrown ArrayIndexOutOfBoundsException");
844 } catch (ArrayIndexOutOfBoundsException t) {
845 ; // Expected results
846 } catch (Throwable t) {
847 fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
848 }
849
850 try {
851 value =
852 PropertyUtils.getIndexedProperty(bean,
853 "dupProperty", 5);
854 fail("Should have thrown ArrayIndexOutOfBoundsException");
855 } catch (ArrayIndexOutOfBoundsException t) {
856 ; // Expected results
857 } catch (Throwable t) {
858 fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
859 }
860
861 try {
862 value =
863 PropertyUtils.getIndexedProperty(bean,
864 "intArray", -1);
865 fail("Should have thrown ArrayIndexOutOfBoundsException");
866 } catch (ArrayIndexOutOfBoundsException t) {
867 ; // Expected results
868 } catch (Throwable t) {
869 fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
870 }
871
872 try {
873 value =
874 PropertyUtils.getIndexedProperty(bean,
875 "intArray", 5);
876 fail("Should have thrown ArrayIndexOutOfBoundsException");
877 } catch (ArrayIndexOutOfBoundsException t) {
878 ; // Expected results
879 } catch (Throwable t) {
880 fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
881 }
882
883 try {
884 value =
885 PropertyUtils.getIndexedProperty(bean,
886 "intIndexed", -1);
887 fail("Should have thrown ArrayIndexOutOfBoundsException");
888 } catch (ArrayIndexOutOfBoundsException t) {
889 ; // Expected results
890 } catch (Throwable t) {
891 fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
892 }
893
894 try {
895 value =
896 PropertyUtils.getIndexedProperty(bean,
897 "intIndexed", 5);
898 fail("Should have thrown ArrayIndexOutOfBoundsException");
899 } catch (ArrayIndexOutOfBoundsException t) {
900 ; // Expected results
901 } catch (Throwable t) {
902 fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
903 }
904
905 try {
906 value =
907 PropertyUtils.getIndexedProperty(bean,
908 "listIndexed", -1);
909 fail("Should have thrown IndexOutOfBoundsException");
910 } catch (IndexOutOfBoundsException t) {
911 ; // Expected results
912 } catch (Throwable t) {
913 fail("Threw " + t + " instead of IndexOutOfBoundsException");
914 }
915
916 try {
917 value =
918 PropertyUtils.getIndexedProperty(bean,
919 "listIndexed", 5);
920 fail("Should have thrown IndexOutOfBoundsException");
921 } catch (IndexOutOfBoundsException t) {
922 ; // Expected results
923 } catch (Throwable t) {
924 fail("Threw " + t + " instead of IndexOutOfBoundsException");
925 }
926
927 try {
928 value =
929 PropertyUtils.getIndexedProperty(bean,
930 "stringArray", -1);
931 fail("Should have thrown ArrayIndexOutOfBoundsException");
932 } catch (ArrayIndexOutOfBoundsException t) {
933 ; // Expected results
934 } catch (Throwable t) {
935 fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
936 }
937
938 try {
939 value =
940 PropertyUtils.getIndexedProperty(bean,
941 "stringArray", 5);
942 fail("Should have thrown ArrayIndexOutOfBoundsException");
943 } catch (ArrayIndexOutOfBoundsException t) {
944 ; // Expected results
945 } catch (Throwable t) {
946 fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
947 }
948
949 try {
950 value =
951 PropertyUtils.getIndexedProperty(bean,
952 "stringIndexed", -1);
953 fail("Should have thrown ArrayIndexOutOfBoundsException");
954 } catch (ArrayIndexOutOfBoundsException t) {
955 ; // Expected results
956 } catch (Throwable t) {
957 fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
958 }
959
960 try {
961 value =
962 PropertyUtils.getIndexedProperty(bean,
963 "stringIndexed", 5);
964 fail("Should have thrown ArrayIndexOutOfBoundsException");
965 } catch (ArrayIndexOutOfBoundsException t) {
966 ; // Expected results
967 } catch (Throwable t) {
968 fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
969 }
970
971 }
972
973
974 /**
975 * Corner cases on getMappedProperty invalid arguments.
976 */
977 public void testGetMappedArguments() {
978
979 // Use explicit key argument
980
981 try {
982 PropertyUtils.getMappedProperty(null, "mappedProperty",
983 "First Key");
984 fail("Should throw IllegalArgumentException 1");
985 } catch (IllegalArgumentException e) {
986 ; // Expected response
987 } catch (Throwable t) {
988 fail("Threw " + t + " instead of IllegalArgumentException 1");
989 }
990
991 try {
992 PropertyUtils.getMappedProperty(bean, null, "First Key");
993 fail("Should throw IllegalArgumentException 2");
994 } catch (IllegalArgumentException e) {
995 ; // Expected response
996 } catch (Throwable t) {
997 fail("Threw " + t + " instead of IllegalArgumentException 2");
998 }
999
1000 try {
1001 PropertyUtils.getMappedProperty(bean, "mappedProperty", null);
1002 fail("Should throw IllegalArgumentException 3");
1003 } catch (IllegalArgumentException e) {
1004 ; // Expected response
1005 } catch (Throwable t) {
1006 fail("Threw " + t + " instead of IllegalArgumentException 3");
1007 }
1008
1009 // Use key expression
1010
1011 try {
1012 PropertyUtils.getMappedProperty(null,
1013 "mappedProperty(First Key)");
1014 fail("Should throw IllegalArgumentException 4");
1015 } catch (IllegalArgumentException e) {
1016 ; // Expected response
1017 } catch (Throwable t) {
1018 fail("Threw " + t + " instead of IllegalArgumentException 4");
1019 }
1020
1021 try {
1022 PropertyUtils.getMappedProperty(bean, "(Second Key)");
1023 fail("Should throw IllegalArgumentException 5");
1024 } catch (NoSuchMethodException e) {
1025 ; // Expected response
1026 } catch (Throwable t) {
1027 fail("Threw " + t + " instead of NoSuchMethodException 5");
1028 }
1029
1030 try {
1031 PropertyUtils.getMappedProperty(bean, "mappedProperty");
1032 fail("Should throw IllegalArgumentException 6");
1033 } catch (IllegalArgumentException e) {
1034 ; // Expected response
1035 } catch (Throwable t) {
1036 fail("Threw " + t + " instead of IllegalArgumentException 6");
1037 }
1038
1039 }
1040
1041
1042 /**
1043 * Test getting mapped values with periods in the key.
1044 */
1045 public void testGetMappedPeriods() {
1046
1047 bean.setMappedProperty("key.with.a.dot", "Special Value");
1048 assertEquals("Can retrieve directly",
1049 "Special Value",
1050 bean.getMappedProperty("key.with.a.dot"));
1051 try {
1052 assertEquals("Can retrieve via getMappedProperty",
1053 "Special Value",
1054 PropertyUtils.getMappedProperty
1055 (bean, "mappedProperty", "key.with.a.dot"));
1056 } catch (Exception e) {
1057 fail("Thew exception: " + e);
1058 }
1059 try {
1060 assertEquals("Can retrieve via getNestedProperty",
1061 "Special Value",
1062 PropertyUtils.getNestedProperty
1063 (bean, "mappedProperty(key.with.a.dot)"));
1064 } catch (Exception e) {
1065 fail("Thew exception: " + e);
1066 }
1067
1068 bean.setMappedObjects("nested.property", new TestBean());
1069 assertNotNull("Can retrieve directly",
1070 bean.getMappedObjects("nested.property"));
1071 try {
1072 assertEquals("Can retrieve nested",
1073 "This is a string",
1074 PropertyUtils.getNestedProperty
1075 (bean,
1076 "mappedObjects(nested.property).stringProperty"));
1077 } catch (Exception e) {
1078 fail("Thew exception: " + e);
1079 }
1080
1081 try
1082 {
1083 assertEquals("Can't retrieved nested with mapped property",
1084 "Mapped Value",
1085 PropertyUtils.getNestedProperty(
1086 bean,"mappedNested.value(Mapped Key)"));
1087 } catch (Exception e)
1088 {
1089 fail("Thew exception: " + e);
1090 }
1091 }
1092
1093
1094 /**
1095 * Test getting mapped values with slashes in the key. This is different
1096 * from periods because slashes are not syntactically significant.
1097 */
1098 public void testGetMappedSlashes() {
1099
1100 bean.setMappedProperty("key/with/a/slash", "Special Value");
1101 assertEquals("Can retrieve directly",
1102 "Special Value",
1103 bean.getMappedProperty("key/with/a/slash"));
1104 try {
1105 assertEquals("Can retrieve via getMappedProperty",
1106 "Special Value",
1107 PropertyUtils.getMappedProperty
1108 (bean, "mappedProperty", "key/with/a/slash"));
1109 } catch (Exception e) {
1110 fail("Thew exception: " + e);
1111 }
1112 try {
1113 assertEquals("Can retrieve via getNestedProperty",
1114 "Special Value",
1115 PropertyUtils.getNestedProperty
1116 (bean, "mappedProperty(key/with/a/slash)"));
1117 } catch (Exception e) {
1118 fail("Thew exception: " + e);
1119 }
1120
1121 bean.setMappedObjects("nested/property", new TestBean());
1122 assertNotNull("Can retrieve directly",
1123 bean.getMappedObjects("nested/property"));
1124 try {
1125 assertEquals("Can retrieve nested",
1126 "This is a string",
1127 PropertyUtils.getNestedProperty
1128 (bean,
1129 "mappedObjects(nested/property).stringProperty"));
1130 } catch (Exception e) {
1131 fail("Thew exception: " + e);
1132 }
1133
1134 }
1135
1136
1137 /**
1138 * Positive and negative tests on getMappedProperty valid arguments.
1139 */
1140 public void testGetMappedValues() {
1141
1142 Object value = null;
1143
1144 // Use explicit key argument
1145
1146 try {
1147 value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
1148 "First Key");
1149 assertEquals("Can find first value", "First Value", value);
1150 } catch (Throwable t) {
1151 fail("Finding first value threw " + t);
1152 }
1153
1154 try {
1155 value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
1156 "Second Key");
1157 assertEquals("Can find second value", "Second Value", value);
1158 } catch (Throwable t) {
1159 fail("Finding second value threw " + t);
1160 }
1161
1162 try {
1163 value = PropertyUtils.getMappedProperty(bean, "mappedProperty",
1164 "Third Key");
1165 assertNull("Can not find third value", value);
1166 } catch (Throwable t) {
1167 fail("Finding third value threw " + t);
1168 }
1169
1170 // Use key expression with parentheses
1171
1172 try {
1173 value =
1174 PropertyUtils.getMappedProperty(bean,
1175 "mappedProperty(First Key)");
1176 assertEquals("Can find first value", "First Value", value);
1177 } catch (Throwable t) {
1178 fail("Finding first value threw " + t);
1179 }
1180
1181 try {
1182 value =
1183 PropertyUtils.getMappedProperty(bean,
1184 "mappedProperty(Second Key)");
1185 assertEquals("Can find second value", "Second Value", value);
1186 } catch (Throwable t) {
1187 fail("Finding second value threw " + t);
1188 }
1189
1190 try {
1191 value =
1192 PropertyUtils.getMappedProperty(bean,
1193 "mappedProperty(Third Key)");
1194 assertNull("Can not find third value", value);
1195 } catch (Throwable t) {
1196 fail("Finding third value threw " + t);
1197 }
1198
1199 // Use key expression with dotted syntax
1200
1201 try {
1202 value =
1203 PropertyUtils.getNestedProperty(bean,
1204 "mapProperty.First Key");
1205 assertEquals("Can find first value", "First Value", value);
1206 } catch (Throwable t) {
1207 fail("Finding first value threw " + t);
1208 }
1209
1210 try {
1211 value =
1212 PropertyUtils.getNestedProperty(bean,
1213 "mapProperty.Second Key");
1214 assertEquals("Can find second value", "Second Value", value);
1215 } catch (Throwable t) {
1216 fail("Finding second value threw " + t);
1217 }
1218
1219 try {
1220 value =
1221 PropertyUtils.getNestedProperty(bean,
1222 "mapProperty.Third Key");
1223 assertNull("Can not find third value", value);
1224 } catch (Throwable t) {
1225 fail("Finding third value threw " + t);
1226 }
1227
1228 }
1229
1230
1231 /**
1232 * Corner cases on getNestedProperty invalid arguments.
1233 */
1234 public void testGetNestedArguments() {
1235
1236 try {
1237 PropertyUtils.getNestedProperty(null, "stringProperty");
1238 fail("Should throw IllegalArgumentException 1");
1239 } catch (IllegalArgumentException e) {
1240 ; // Expected response
1241 } catch (Throwable t) {
1242 fail("Threw " + t + " instead of IllegalArgumentException 1");
1243 }
1244
1245 try {
1246 PropertyUtils.getNestedProperty(bean, null);
1247 fail("Should throw IllegalArgumentException 2");
1248 } catch (IllegalArgumentException e) {
1249 ; // Expected response
1250 } catch (Throwable t) {
1251 fail("Threw " + t + " instead of IllegalArgumentException 2");
1252 }
1253
1254 }
1255
1256
1257 /**
1258 * Test getNestedProperty on a boolean property.
1259 */
1260 public void testGetNestedBoolean() {
1261
1262 try {
1263 Object value =
1264 PropertyUtils.getNestedProperty
1265 (bean, "nested.booleanProperty");
1266 assertNotNull("Got a value", value);
1267 assertTrue("Got correct type", (value instanceof Boolean));
1268 assertTrue("Got correct value",
1269 ((Boolean) value).booleanValue() ==
1270 bean.getNested().getBooleanProperty());
1271 } catch (IllegalAccessException e) {
1272 fail("IllegalAccessException");
1273 } catch (IllegalArgumentException e) {
1274 fail("IllegalArgumentException");
1275 } catch (InvocationTargetException e) {
1276 fail("InvocationTargetException");
1277 } catch (NoSuchMethodException e) {
1278 fail("NoSuchMethodException");
1279 }
1280
1281 }
1282
1283
1284 /**
1285 * Test getNestedProperty on a double property.
1286 */
1287 public void testGetNestedDouble() {
1288
1289 try {
1290 Object value =
1291 PropertyUtils.getNestedProperty