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    *      http://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  package org.apache.commons.beanutils;
18  
19  import java.lang.reflect.InvocationTargetException;
20  import java.util.ArrayList;
21  import java.util.HashMap;
22  import java.util.LinkedList;
23  import java.util.TreeMap;
24  
25  import junit.framework.Test;
26  import junit.framework.TestCase;
27  import junit.framework.TestSuite;
28  
29  /**
30   * <p>Test Case for the <code>LazyDynaBean</code> implementation class.</p>
31   *
32   * @version $Id$
33   */
34  public class LazyDynaBeanTestCase extends TestCase {
35  
36      protected LazyDynaBean  bean      = null;
37      protected LazyDynaClass dynaClass = null;
38      protected String testProperty     = "myProperty";
39      protected String testPropertyA    = "myProperty-A";
40      protected String testPropertyB    = "myProperty-B";
41      protected String testString1      = "myStringValue-1";
42      protected String testString2      = "myStringValue-2";
43      protected Integer testInteger1    = new Integer(30);
44      protected Integer testInteger2    = new Integer(40);
45      protected String testKey          = "myKey";
46  
47      // ---------------------------------------------------------- Constructors
48  
49      /**
50       * Construct a new instance of this test case.
51       *
52       * @param name Name of the test case
53       */
54      public LazyDynaBeanTestCase(final String name) {
55          super(name);
56      }
57  
58      // -------------------------------------------------- Overall Test Methods
59  
60      /**
61       * Run thus Test
62       */
63      public static void main(final String[] args) {
64          junit.textui.TestRunner.run(suite());
65      }
66  
67      /**
68       * Return the tests included in this test suite.
69       */
70      public static Test suite() {
71          return (new TestSuite(LazyDynaBeanTestCase.class));
72      }
73  
74      /**
75       * Set up instance variables required by this test case.
76       */
77      @Override
78      public void setUp() throws Exception {
79          bean = new LazyDynaBean();
80          dynaClass = (LazyDynaClass)bean.getDynaClass();
81          dynaClass.setReturnNull(true);
82      }
83  
84      /**
85       * Tear down instance variables required by this test case.
86       */
87      @Override
88      public void tearDown() {
89        bean = null;
90      }
91  
92      // ------------------------------------------------ Individual Test Methods
93  
94      /**
95       * Test Getting/Setting a Simple Property
96       */
97      public void testSimpleProperty() {
98  
99          // Check the property & value doesn't exist
100         assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
101         assertNull("Check Value is null", bean.get(testProperty));
102 
103         // Set a new property - should add new property and set value
104         bean.set(testProperty, testInteger1);
105         assertEquals("Check First Value is correct", testInteger1, bean.get(testProperty));
106         assertEquals("Check Property type is correct", Integer.class, dynaClass.getDynaProperty(testProperty).getType());
107 
108         // Set the property again - should set the new value
109         bean.set(testProperty, testInteger2);
110         assertEquals("Check Second Value is correct", testInteger2, bean.get(testProperty));
111 
112         // Set the property again - with a different type, should fail
113         try {
114             bean.set(testProperty, testString1);
115             fail("expected ConversionException trying to set an Integer property to a String");
116         } catch (final ConversionException expected) {
117             // expected result
118         }
119 
120     }
121 
122     /**
123      * Test Getting/Setting a 'null' Property
124      */
125     public void testNullProperty() {
126 
127         // Check the property & value doesn't exist
128         assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
129         assertNull("Check Value is null", bean.get(testProperty));
130 
131         // Set a new property to null
132         bean.set(testProperty, null);
133         assertNull("Check Value is still null", bean.get(testProperty));
134 
135     }
136 
137     /**
138      * Test Setting a Simple Property when MutableDynaClass is set to restricted
139      */
140     public void testSimplePropertyRestricted() {
141 
142         // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
143         dynaClass.setRestricted(true);
144         assertTrue("Check MutableDynaClass is restricted", dynaClass.isRestricted());
145 
146         // Check the property & value doesn't exist
147         assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
148         assertNull("Check Value is null", bean.get(testProperty));
149 
150         // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
151         try {
152             bean.set(testProperty, testString1);
153             fail("expected IllegalArgumentException trying to add new property to restricted DynaClass");
154         } catch (final IllegalArgumentException expected) {
155             // expected result
156         }
157 
158     }
159 
160     /**
161      * Test Getting/Setting a 'Mapped' Property - default HashMap property
162      */
163     public void testMappedPropertyDefault() {
164 
165         // Check the property & value doesn't exist
166         assertNull("Check Mapped Property doesn't exist", dynaClass.getDynaProperty(testProperty));
167         assertNull("Check Map is null", bean.get(testProperty));
168         assertNull("Check Mapped Value is null", bean.get(testProperty, testKey));
169 
170         // Set a new mapped property - should add new HashMap property and set the mapped value
171         bean.set(testProperty, testKey, testInteger1);
172         assertEquals("Check Mapped Property exists", HashMap.class, bean.get(testProperty).getClass());
173         assertEquals("Check First Mapped Value is correct(a)", testInteger1, bean.get(testProperty, testKey));
174         assertEquals("Check First Mapped Value is correct(b)", testInteger1, ((HashMap<?, ?>)bean.get(testProperty)).get(testKey));
175 
176         // Set the property again - should set the new value
177         bean.set(testProperty, testKey, testInteger2);
178         assertEquals("Check Second Mapped Value is correct(a)", testInteger2, bean.get(testProperty, testKey));
179         assertEquals("Check Second Mapped Value is correct(b)", testInteger2, ((HashMap<?, ?>)bean.get(testProperty)).get(testKey));
180     }
181 
182     /**
183      * Test Getting/Setting a 'Mapped' Property - use TreeMap property
184      */
185     public void testMappedPropertyTreeMap() {
186 
187         // Check the property & value doesn't exist
188         assertNull("Check Mapped Property doesn't exist", dynaClass.getDynaProperty(testProperty));
189 
190         // Add a 'TreeMap' property to the DynaClass
191         dynaClass.add(testProperty, TreeMap.class);
192         assertTrue("Check Property is mapped", dynaClass.getDynaProperty(testProperty).isMapped());
193         assertEquals("Check Property is correct type", TreeMap.class, dynaClass.getDynaProperty(testProperty).getType());
194         assertEquals("Check Mapped Property exists", TreeMap.class, bean.get(testProperty).getClass());
195 //        assertNull("Check mapped property is null", bean.get(testProperty));
196 
197         // Set a new mapped property - should instatiate a new TreeMap property and set the mapped value
198         bean.set(testProperty, testKey, testInteger1);
199         assertEquals("Check Mapped Property exists", TreeMap.class, bean.get(testProperty).getClass());
200         assertEquals("Check First Mapped Value is correct(a)", testInteger1, bean.get(testProperty, testKey));
201         assertEquals("Check First Mapped Value is correct(b)", testInteger1, ((TreeMap<?, ?>)bean.get(testProperty)).get(testKey));
202 
203         // Set the property again - should set the new value
204         bean.set(testProperty, testKey, testInteger2);
205         assertEquals("Check Second Mapped Value is correct(a)", testInteger2, bean.get(testProperty, testKey));
206         assertEquals("Check Second Mapped Value is correct(b)", testInteger2, ((TreeMap<?, ?>)bean.get(testProperty)).get(testKey));
207     }
208 
209     /**
210      * Test Setting a 'Mapped' Property using PropertyUtils
211      */
212     public void testMappedPropertyUtils() {
213 
214         dynaClass.setReturnNull(false);
215 
216         // Check the property & value doesn't exist
217         assertFalse("Check Mapped Property doesn't exist", dynaClass.isDynaProperty(testProperty));
218         assertNull("Check Map is null", bean.get(testProperty));
219         assertNull("Check Mapped Value is null", bean.get(testProperty, testKey));
220 
221         // Set the mapped property using PropertyUtils
222         try {
223           PropertyUtils.setProperty(bean, testProperty+"("+testKey+")", testString1);
224         }
225         catch (final NoSuchMethodException ex) {
226             fail("testIndexedPropertyUtils threw "+ex);
227         }
228         catch (final InvocationTargetException ex) {
229             fail("testIndexedPropertyUtils threw "+ex);
230         }
231         catch (final IllegalAccessException ex) {
232             fail("testIndexedPropertyUtils threw "+ex);
233         }
234 
235         // Check property value correctly set
236         assertEquals("Check Mapped Bean Value is correct", testString1, bean.get(testProperty, testKey));
237 
238     }
239 
240     /**
241      * Test Setting a Mapped Property when MutableDynaClass is set to restricted
242      */
243     public void testMappedPropertyRestricted() {
244 
245         // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
246         dynaClass.setRestricted(true);
247         assertTrue("Check MutableDynaClass is restricted", dynaClass.isRestricted());
248 
249         // Check the property & value doesn't exist
250         assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
251         assertNull("Check Value is null", bean.get(testProperty));
252 
253         // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
254         try {
255             bean.set(testProperty, testKey, testInteger1);
256             fail("expected IllegalArgumentException trying to add new property to restricted MutableDynaClass");
257         } catch (final IllegalArgumentException expected) {
258             // expected result
259         }
260 
261     }
262 
263     /**
264      * Test setting mapped property for type which is not Map
265      */
266     public void testMappedInvalidType() {
267         dynaClass.add(testProperty, String.class);
268         assertFalse("Check Property is not mapped", dynaClass.getDynaProperty(testProperty).isMapped());
269         try {
270             bean.set(testProperty, testKey, testInteger1);
271             fail("set(property, key, value) should have thrown IllegalArgumentException");
272         } catch (final IllegalArgumentException expected) {
273             // expected result
274         }
275     }
276 
277     /**
278      * Test Getting/Setting an 'Indexed' Property - default ArrayList property
279      */
280     public void testIndexedPropertyDefault() {
281 
282         int index = 3;
283 
284         // Check the property & value doesn't exist
285         assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
286         assertNull("Check Indexed Property is null", bean.get(testProperty));
287         assertNull("Check Indexed value is null", bean.get(testProperty, index));
288 
289         // Set the property, should create new ArrayList and set appropriate indexed value
290         bean.set(testProperty, index, testInteger1);
291         assertNotNull("Check Indexed Property is not null", bean.get(testProperty));
292         assertEquals("Check Indexed Property is correct type", ArrayList.class, bean.get(testProperty).getClass());
293         assertEquals("Check First Indexed Value is correct", testInteger1, bean.get(testProperty, index));
294         assertEquals("Check First Array length is correct", new Integer(index+1),  new Integer(((ArrayList<?>)bean.get(testProperty)).size()));
295 
296         // Set a second indexed value, should automatically grow the ArrayList and set appropriate indexed value
297         index = index + 2;
298         bean.set(testProperty, index, testString1);
299         assertEquals("Check Second Indexed Value is correct", testString1, bean.get(testProperty, index));
300         assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((ArrayList<?>)bean.get(testProperty)).size()));
301     }
302 
303     /**
304      * Test Getting/Setting a List 'Indexed' Property - use alternative List (LinkedList)
305      */
306     public void testIndexedLinkedList() {
307 
308         int   index     = 3;
309 
310         // Check the property & value doesn't exist
311         assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
312         assertNull("Check Indexed Property is null", bean.get(testProperty));
313 
314         // Add a 'LinkedList' property to the DynaClass
315         dynaClass.add(testProperty, LinkedList.class);
316         assertTrue("Check Property is indexed", dynaClass.getDynaProperty(testProperty).isIndexed());
317         assertEquals("Check Property is correct type", LinkedList.class, dynaClass.getDynaProperty(testProperty).getType());
318         assertEquals("Check Property type is correct", LinkedList.class, bean.get(testProperty).getClass());
319 
320         // Set the property, should instantiate a new LinkedList and set appropriate indexed value
321         bean.set(testProperty, index, testString1);
322         assertEquals("Check Property type is correct", LinkedList.class, bean.get(testProperty).getClass());
323         assertEquals("Check First Indexed Value is correct", testString1, bean.get(testProperty, index));
324         assertEquals("Check First Array length is correct", new Integer(index+1),  new Integer(((LinkedList<?>)bean.get(testProperty)).size()));
325 
326         // Set a second indexed value, should automatically grow the LinkedList and set appropriate indexed value
327         index = index + 2;
328         bean.set(testProperty, index, testInteger1);
329         assertEquals("Check Second Indexed Value is correct", testInteger1, bean.get(testProperty, index));
330         assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((LinkedList<?>)bean.get(testProperty)).size()));
331     }
332 
333     /**
334      * Test Getting/Setting a primitive array 'Indexed' Property - use int[]
335      */
336     public void testIndexedPrimitiveArray() {
337 
338         int   index     = 3;
339         final int[] primitiveArray = new int[0];
340 
341         // Check the property & value doesn't exist
342         assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
343         assertNull("Check Indexed Property is null", bean.get(testProperty));
344 
345         // Add a DynaProperty of type int[]
346         dynaClass.add(testProperty, primitiveArray.getClass());
347         assertEquals("Check Indexed Property exists", primitiveArray.getClass(), dynaClass.getDynaProperty(testProperty).getType());
348         assertEquals("Check Indexed Property is correct type", primitiveArray.getClass(), bean.get(testProperty).getClass());
349 
350         // Set an indexed value
351         bean.set(testProperty, index, testInteger1);
352         assertNotNull("Check Indexed Property is not null", bean.get(testProperty));
353         assertEquals("Check Indexed Property is correct type", primitiveArray.getClass(), bean.get(testProperty).getClass());
354         assertEquals("Check First Indexed Value is correct(a)", testInteger1, bean.get(testProperty, index));
355         assertEquals("Check First Indexed Value is correct(b)", testInteger1, new Integer(((int[])bean.get(testProperty))[index]));
356         assertEquals("Check Array length is correct", new Integer(index+1),  new Integer(((int[])bean.get(testProperty)).length));
357 
358         // Set a second indexed value, should automatically grow the int[] and set appropriate indexed value
359         index = index + 2;
360         bean.set(testProperty, index, testInteger2);
361         assertEquals("Check Second Indexed Value is correct(a)", testInteger2, bean.get(testProperty, index));
362         assertEquals("Check Second Indexed Value is correct(b)", testInteger2, new Integer(((int[])bean.get(testProperty))[index]));
363         assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((int[])bean.get(testProperty)).length));
364 
365     }
366 
367     /**
368      * Test Getting/Setting an Object array 'Indexed' Property - use String[]
369      */
370     public void testIndexedObjectArray() {
371 
372         int   index     = 3;
373         final Object objectArray = new String[0];
374 
375         // Check the property & value doesn't exist
376         assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
377         assertNull("Check Indexed Property is null", bean.get(testProperty));
378 
379         // Add a DynaProperty of type String[]
380         dynaClass.add(testProperty, objectArray.getClass());
381         assertEquals("Check Indexed Property exists", objectArray.getClass(), dynaClass.getDynaProperty(testProperty).getType());
382         assertEquals("Check Indexed Property is correct type", objectArray.getClass(), bean.get(testProperty).getClass());
383 
384         // Set an indexed value
385         bean.set(testProperty, index, testString1);
386         assertNotNull("Check Indexed Property is not null", bean.get(testProperty));
387         assertEquals("Check Indexed Property is correct type", objectArray.getClass(), bean.get(testProperty).getClass());
388         assertEquals("Check First Indexed Value is correct(a)", testString1, bean.get(testProperty, index));
389         assertEquals("Check First Indexed Value is correct(b)", testString1, ((String[])bean.get(testProperty))[index]);
390         assertEquals("Check Array length is correct", new Integer(index+1),  new Integer(((String[])bean.get(testProperty)).length));
391 
392         // Set a second indexed value, should automatically grow the String[] and set appropriate indexed value
393         index = index + 2;
394         bean.set(testProperty, index, testString2);
395         assertEquals("Check Second Indexed Value is correct(a)", testString2, bean.get(testProperty, index));
396         assertEquals("Check Second Indexed Value is correct(b)", testString2, ((String[])bean.get(testProperty))[index]);
397         assertEquals("Check Second Array length is correct", new Integer(index+1),  new Integer(((String[])bean.get(testProperty)).length));
398     }
399 
400     /**
401      * Test Getting/Setting an DynaBean[] array
402      */
403     public void testIndexedDynaBeanArray() {
404 
405         final int   index     = 3;
406         final Object objectArray = new LazyDynaMap[0];
407 
408         // Check the property & value doesn't exist
409         assertNull("Check Indexed Property doesn't exist", dynaClass.getDynaProperty(testProperty));
410         assertNull("Check Indexed Property is null", bean.get(testProperty));
411 
412         // Add a DynaProperty of type String[]
413         dynaClass.add(testProperty, objectArray.getClass());
414         assertEquals("Check Indexed Property exists", objectArray.getClass(), dynaClass.getDynaProperty(testProperty).getType());
415         assertEquals("Check Indexed Property is correct type", objectArray.getClass(), bean.get(testProperty).getClass());
416 
417         // Retrieving from Array should initialize DynaBean
418         for (int i = index; i >= 0; i--) {
419             assertEquals("Check Array Components initialized", LazyDynaMap.class, bean.get(testProperty, index).getClass());
420         }
421 
422         dynaClass.add(testPropertyB, objectArray.getClass());
423         final LazyDynaMap newMap = new LazyDynaMap();
424         newMap.set(testPropertyB, testString2);
425         bean.set(testPropertyA, index, newMap);
426         assertEquals("Check Indexed Value is correct(a)", testString2, ((DynaBean)bean.get(testPropertyA, index)).get(testPropertyB));
427 
428     }
429 
430     /**
431      * Test Setting an 'Indexed' Property using PropertyUtils
432      */
433     public void testIndexedPropertyUtils() {
434 
435         final int   index     = 3;
436         dynaClass.setReturnNull(false);
437 
438         // Check the property & value doesn't exist
439         assertFalse("Check Indexed Property doesn't exist", dynaClass.isDynaProperty(testProperty));
440         assertNull("Check Indexed Property is null", bean.get(testProperty));
441         assertNull("Check Indexed value is null", bean.get(testProperty, index));
442 
443         // Use PropertyUtils to set the indexed value
444         try {
445           PropertyUtils.setProperty(bean, testProperty+"["+index+"]", testString1);
446         }
447         catch (final NoSuchMethodException ex) {
448             fail("testIndexedPropertyUtils threw "+ex);
449         }
450         catch (final InvocationTargetException ex) {
451             fail("testIndexedPropertyUtils threw "+ex);
452         }
453         catch (final IllegalAccessException ex) {
454             fail("testIndexedPropertyUtils threw "+ex);
455         }
456 
457         // Check property value correctly set
458         assertEquals("Check Indexed Bean Value is correct", testString1, bean.get(testProperty, index));
459 
460     }
461 
462     /**
463      * Test Setting an Indexed Property when MutableDynaClass is set to restricted
464      */
465     public void testIndexedPropertyRestricted() {
466 
467         final int   index     = 3;
468 
469         // Set the MutableDyanClass to 'restricted' (i.e. no new properties cab be added
470         dynaClass.setRestricted(true);
471         assertTrue("Check MutableDynaClass is restricted", dynaClass.isRestricted());
472 
473         // Check the property & value doesn't exist
474         assertNull("Check Property doesn't exist", dynaClass.getDynaProperty(testProperty));
475         assertNull("Check Value is null", bean.get(testProperty));
476 
477         // Set the property - should fail because property doesn't exist and MutableDynaClass is restricted
478         try {
479             bean.set(testProperty, index, testInteger1);
480             fail("expected IllegalArgumentException trying to add new property to restricted MutableDynaClass");
481         } catch (final IllegalArgumentException expected) {
482             // expected result
483         }
484 
485     }
486 
487     /**
488      * Test setting indexed property for type which is not List or Array
489      */
490     public void testIndexedInvalidType() {
491         final int   index     = 3;
492         dynaClass.add(testProperty, String.class);
493         assertFalse("Check Property is not indexed", dynaClass.getDynaProperty(testProperty).isIndexed());
494         try {
495             bean.set(testProperty, index, testString1);
496             fail("set(property, index, value) should have thrown IllegalArgumentException");
497         } catch (final IllegalArgumentException expected) {
498             // expected result
499         }
500     }
501 
502 }