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.configuration.beanutils;
18  
19  import static org.junit.Assert.assertEquals;
20  import static org.junit.Assert.assertNotNull;
21  import static org.junit.Assert.assertNull;
22  import static org.junit.Assert.assertSame;
23  import static org.junit.Assert.assertTrue;
24  
25  import java.util.HashMap;
26  import java.util.Map;
27  
28  import org.apache.commons.configuration.ConfigurationRuntimeException;
29  import org.junit.After;
30  import org.junit.Before;
31  import org.junit.Test;
32  
33  /**
34   * Test class for BeanHelper.
35   *
36   * @since 1.3
37   * @author <a
38   * href="http://commons.apache.org/configuration/team-list.html">Commons
39   * Configuration team</a>
40   * @version $Id: TestBeanHelper.java 1225344 2011-12-28 21:28:23Z oheger $
41   */
42  public class TestBeanHelper
43  {
44      /** Constant for the name of the test bean factory. */
45      private static final String TEST_FACTORY = "testFactory";
46  
47      /**
48       * Stores the default bean factory. Because this is a static field in
49       * BeanHelper it is temporarily stored and reset after the tests.
50       */
51      private BeanFactory tempDefaultBeanFactory;
52  
53      @Before
54      public void setUp() throws Exception
55      {
56          tempDefaultBeanFactory = BeanHelper.getDefaultBeanFactory();
57          deregisterFactories();
58      }
59  
60      @After
61      public void tearDown() throws Exception
62      {
63          deregisterFactories();
64  
65          // Reset old default bean factory
66          BeanHelper.setDefaultBeanFactory(tempDefaultBeanFactory);
67      }
68  
69      /**
70       * Removes all bean factories that might have been registered during a test.
71       */
72      private void deregisterFactories()
73      {
74          for (String name : BeanHelper.registeredFactoryNames())
75          {
76              BeanHelper.deregisterBeanFactory(name);
77          }
78          assertTrue("Remaining registered bean factories", BeanHelper
79                  .registeredFactoryNames().isEmpty());
80      }
81  
82      /**
83       * Tests registering a new bean factory.
84       */
85      @Test
86      public void testRegisterBeanFactory()
87      {
88          assertTrue("List of registered factories is not empty", BeanHelper
89                  .registeredFactoryNames().isEmpty());
90          BeanHelper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory());
91          assertEquals("Wrong number of registered factories", 1, BeanHelper
92                  .registeredFactoryNames().size());
93          assertTrue("Test factory is not contained", BeanHelper
94                  .registeredFactoryNames().contains(TEST_FACTORY));
95      }
96  
97      /**
98       * Tries to register a null factory. This should cause an exception.
99       */
100     @Test(expected = IllegalArgumentException.class)
101     public void testRegisterBeanFactoryNull()
102     {
103         BeanHelper.registerBeanFactory(TEST_FACTORY, null);
104     }
105 
106     /**
107      * Tries to register a bean factory with a null name. This should cause an
108      * exception.
109      */
110     @Test(expected = IllegalArgumentException.class)
111     public void testRegisterBeanFactoryNullName()
112     {
113         BeanHelper.registerBeanFactory(null, new TestBeanFactory());
114     }
115 
116     /**
117      * Tests to deregister a bean factory.
118      */
119     @Test
120     public void testDeregisterBeanFactory()
121     {
122         assertNull("deregistering non existing factory", BeanHelper
123                 .deregisterBeanFactory(TEST_FACTORY));
124         assertNull("deregistering null factory", BeanHelper
125                 .deregisterBeanFactory(null));
126         BeanFactory factory = new TestBeanFactory();
127         BeanHelper.registerBeanFactory(TEST_FACTORY, factory);
128         assertSame("Could not deregister factory", factory, BeanHelper
129                 .deregisterBeanFactory(TEST_FACTORY));
130         assertTrue("List of factories is not empty", BeanHelper
131                 .registeredFactoryNames().isEmpty());
132     }
133 
134     /**
135      * Tests whether the default bean factory is correctly initialized.
136      */
137     @Test
138     public void testGetDefaultBeanFactory()
139     {
140         assertSame("Incorrect default bean factory",
141                 DefaultBeanFactory.INSTANCE, tempDefaultBeanFactory);
142     }
143 
144     /**
145      * Tests setting the default bean factory to null. This should caus an
146      * exception.
147      */
148     @Test(expected = IllegalArgumentException.class)
149     public void testSetDefaultBeanFactoryNull()
150     {
151         BeanHelper.setDefaultBeanFactory(null);
152     }
153 
154     /**
155      * Tests initializing a bean.
156      */
157     @Test
158     public void testInitBean()
159     {
160         BeanHelper.setDefaultBeanFactory(new TestBeanFactory());
161         TestBeanDeclaration data = setUpBeanDeclaration();
162         TestBean bean = new TestBean();
163         BeanHelper.initBean(bean, data);
164         checkBean(bean);
165     }
166 
167     /**
168      * Tests initializing a bean when the bean declaration does not contain any
169      * data.
170      */
171     @Test
172     public void testInitBeanWithNoData()
173     {
174         TestBeanDeclaration data = new TestBeanDeclaration();
175         TestBean bean = new TestBean();
176         BeanHelper.initBean(bean, data);
177         assertNull("Wrong string property", bean.getStringValue());
178         assertEquals("Wrong int property", 0, bean.getIntValue());
179         assertNull("Buddy was set", bean.getBuddy());
180     }
181 
182     /**
183      * Tries to initialize a bean with a bean declaration that contains an
184      * invalid property value. This should cause an exception.
185      */
186     @Test(expected = ConfigurationRuntimeException.class)
187     public void testInitBeanWithInvalidProperty()
188     {
189         TestBeanDeclaration data = setUpBeanDeclaration();
190         data.getBeanProperties().put("nonExistingProperty", Boolean.TRUE);
191         BeanHelper.initBean(new TestBean(), data);
192     }
193 
194     /**
195      * Tests creating a bean. All necessary information is stored in the bean
196      * declaration.
197      */
198     @Test
199     public void testCreateBean()
200     {
201         TestBeanFactory factory = new TestBeanFactory();
202         BeanHelper.registerBeanFactory(TEST_FACTORY, factory);
203         TestBeanDeclaration data = setUpBeanDeclaration();
204         data.setBeanFactoryName(TEST_FACTORY);
205         data.setBeanClassName(TestBean.class.getName());
206         checkBean((TestBean) BeanHelper.createBean(data, null));
207         assertNull("A parameter was passed", factory.parameter);
208     }
209 
210     /**
211      * Tests creating a bean when no bean declaration is provided. This should
212      * cause an exception.
213      */
214     @Test(expected = IllegalArgumentException.class)
215     public void testCreateBeanWithNullDeclaration()
216     {
217         BeanHelper.createBean(null);
218     }
219 
220     /**
221      * Tests creating a bean. The bean's class is specified as the default class
222      * argument.
223      */
224     @Test
225     public void testCreateBeanWithDefaultClass()
226     {
227         BeanHelper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory());
228         TestBeanDeclaration data = setUpBeanDeclaration();
229         data.setBeanFactoryName(TEST_FACTORY);
230         checkBean((TestBean) BeanHelper.createBean(data, TestBean.class));
231     }
232 
233     /**
234      * Tests creating a bean when the bean's class is specified as the default
235      * class of the bean factory.
236      */
237     @Test
238     public void testCreateBeanWithFactoryDefaultClass()
239     {
240         TestBeanFactory factory = new TestBeanFactory();
241         factory.supportsDefaultClass = true;
242         BeanHelper.registerBeanFactory(TEST_FACTORY, factory);
243         TestBeanDeclaration data = setUpBeanDeclaration();
244         data.setBeanFactoryName(TEST_FACTORY);
245         checkBean((TestBean) BeanHelper.createBean(data, null));
246     }
247 
248     /**
249      * Tries to create a bean when no class is provided. This should cause an
250      * exception.
251      */
252     @Test(expected = ConfigurationRuntimeException.class)
253     public void testCreateBeanWithNoClass()
254     {
255         BeanHelper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory());
256         TestBeanDeclaration data = setUpBeanDeclaration();
257         data.setBeanFactoryName(TEST_FACTORY);
258         BeanHelper.createBean(data, null);
259     }
260 
261     /**
262      * Tries to create a bean with a non existing class. This should cause an
263      * exception.
264      */
265     @Test(expected = ConfigurationRuntimeException.class)
266     public void testCreateBeanWithInvalidClass()
267     {
268         BeanHelper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory());
269         TestBeanDeclaration data = setUpBeanDeclaration();
270         data.setBeanFactoryName(TEST_FACTORY);
271         data.setBeanClassName("non.existing.ClassName");
272         BeanHelper.createBean(data, null);
273     }
274 
275     /**
276      * Tests creating a bean using the default bean factory.
277      */
278     @Test
279     public void testCreateBeanWithDefaultFactory()
280     {
281         BeanHelper.setDefaultBeanFactory(new TestBeanFactory());
282         TestBeanDeclaration data = setUpBeanDeclaration();
283         data.setBeanClassName(TestBean.class.getName());
284         checkBean((TestBean) BeanHelper.createBean(data, null));
285     }
286 
287     /**
288      * Tests creating a bean using a non registered factory.
289      */
290     @Test(expected = ConfigurationRuntimeException.class)
291     public void testCreateBeanWithUnknownFactory()
292     {
293         TestBeanDeclaration data = setUpBeanDeclaration();
294         data.setBeanFactoryName(TEST_FACTORY);
295         data.setBeanClassName(TestBean.class.getName());
296         BeanHelper.createBean(data, null);
297     }
298 
299     /**
300      * Tests creating a bean when the factory throws an exception.
301      */
302     @Test(expected = ConfigurationRuntimeException.class)
303     public void testCreateBeanWithException()
304     {
305         BeanHelper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory());
306         TestBeanDeclaration data = setUpBeanDeclaration();
307         data.setBeanFactoryName(TEST_FACTORY);
308         data.setBeanClassName(getClass().getName());
309         BeanHelper.createBean(data, null);
310     }
311 
312     /**
313      * Tests if a parameter is correctly passed to the bean factory.
314      */
315     @Test
316     public void testCreateBeanWithParameter()
317     {
318         Object param = new Integer(42);
319         TestBeanFactory factory = new TestBeanFactory();
320         BeanHelper.registerBeanFactory(TEST_FACTORY, factory);
321         TestBeanDeclaration data = setUpBeanDeclaration();
322         data.setBeanFactoryName(TEST_FACTORY);
323         data.setBeanClassName(TestBean.class.getName());
324         checkBean((TestBean) BeanHelper.createBean(data, null, param));
325         assertSame("Wrong parameter", param, factory.parameter);
326     }
327 
328     /**
329      * Returns an initialized bean declaration.
330      *
331      * @return the bean declaration
332      */
333     private TestBeanDeclaration setUpBeanDeclaration()
334     {
335         TestBeanDeclaration data = new TestBeanDeclaration();
336         Map<String, Object> properties = new HashMap<String, Object>();
337         properties.put("stringValue", "testString");
338         properties.put("intValue", "42");
339         data.setBeanProperties(properties);
340         TestBeanDeclaration buddyData = new TestBeanDeclaration();
341         Map<String, Object> properties2 = new HashMap<String, Object>();
342         properties2.put("stringValue", "Another test string");
343         properties2.put("intValue", new Integer(100));
344         buddyData.setBeanProperties(properties2);
345         buddyData.setBeanClassName(TestBean.class.getName());
346         if (BeanHelper.getDefaultBeanFactory() == null)
347         {
348             buddyData.setBeanFactoryName(TEST_FACTORY);
349         }
350         Map<String, Object> nested = new HashMap<String, Object>();
351         nested.put("buddy", buddyData);
352         data.setNestedBeanDeclarations(nested);
353         return data;
354     }
355 
356     /**
357      * Tests if the bean was correctly initialized from the data of the test
358      * bean declaration.
359      *
360      * @param bean the bean to be checked
361      */
362     private void checkBean(TestBean bean)
363     {
364         assertEquals("Wrong string property", "testString", bean
365                 .getStringValue());
366         assertEquals("Wrong int property", 42, bean.getIntValue());
367         TestBean buddy = bean.getBuddy();
368         assertNotNull("Buddy was not set", buddy);
369         assertEquals("Wrong string property in buddy", "Another test string",
370                 buddy.getStringValue());
371         assertEquals("Wrong int property in buddy", 100, buddy.getIntValue());
372     }
373 
374     /**
375      * A simple bean class used for testing creation operations.
376      */
377     public static class TestBean
378     {
379         private String stringValue;
380 
381         private int intValue;
382 
383         private TestBean buddy;
384 
385         public TestBean getBuddy()
386         {
387             return buddy;
388         }
389 
390         public void setBuddy(TestBean buddy)
391         {
392             this.buddy = buddy;
393         }
394 
395         public int getIntValue()
396         {
397             return intValue;
398         }
399 
400         public void setIntValue(int intValue)
401         {
402             this.intValue = intValue;
403         }
404 
405         public String getStringValue()
406         {
407             return stringValue;
408         }
409 
410         public void setStringValue(String stringValue)
411         {
412             this.stringValue = stringValue;
413         }
414     }
415 
416     /**
417      * An implementation of the BeanFactory interface used for testing. This
418      * implementation is really simple: If the TestBean class is provided, a new
419      * instance will be created. Otherwise an exception is thrown.
420      */
421     static class TestBeanFactory implements BeanFactory
422     {
423         Object parameter;
424 
425         boolean supportsDefaultClass;
426 
427         public Object createBean(Class<?> beanClass, BeanDeclaration data, Object param)
428                 throws Exception
429         {
430             parameter = param;
431             if (TestBean.class.equals(beanClass))
432             {
433                 TestBean bean = new TestBean();
434                 BeanHelper.initBean(bean, data);
435                 return bean;
436             }
437             else
438             {
439                 throw new IllegalArgumentException("Unsupported class: "
440                         + beanClass);
441             }
442         }
443 
444         /**
445          * Returns the default class, but only if the supportsDefaultClass flag
446          * is set.
447          */
448         public Class<?> getDefaultBeanClass()
449         {
450             return supportsDefaultClass ? TestBean.class : null;
451         }
452     }
453 
454     /**
455      * A test implementation of the BeanDeclaration interface. This
456      * implementation allows to set the values directly, which should be
457      * returned by the methods required by the BeanDeclaration interface.
458      */
459     static class TestBeanDeclaration implements BeanDeclaration
460     {
461         private String beanClassName;
462 
463         private String beanFactoryName;
464 
465         private Object beanFactoryParameter;
466 
467         private Map<String, Object> beanProperties;
468 
469         private Map<String, Object> nestedBeanDeclarations;
470 
471         public String getBeanClassName()
472         {
473             return beanClassName;
474         }
475 
476         public void setBeanClassName(String beanClassName)
477         {
478             this.beanClassName = beanClassName;
479         }
480 
481         public String getBeanFactoryName()
482         {
483             return beanFactoryName;
484         }
485 
486         public void setBeanFactoryName(String beanFactoryName)
487         {
488             this.beanFactoryName = beanFactoryName;
489         }
490 
491         public Object getBeanFactoryParameter()
492         {
493             return beanFactoryParameter;
494         }
495 
496         public void setBeanFactoryParameter(Object beanFactoryParameter)
497         {
498             this.beanFactoryParameter = beanFactoryParameter;
499         }
500 
501         public Map<String, Object> getBeanProperties()
502         {
503             return beanProperties;
504         }
505 
506         public void setBeanProperties(Map<String, Object> beanProperties)
507         {
508             this.beanProperties = beanProperties;
509         }
510 
511         public Map<String, Object> getNestedBeanDeclarations()
512         {
513             return nestedBeanDeclarations;
514         }
515 
516         public void setNestedBeanDeclarations(Map<String, Object> nestedBeanDeclarations)
517         {
518             this.nestedBeanDeclarations = nestedBeanDeclarations;
519         }
520     }
521 }