001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.commons.configuration.beanutils; 018 019 import static org.junit.Assert.assertEquals; 020 import static org.junit.Assert.assertNotNull; 021 import static org.junit.Assert.assertNull; 022 import static org.junit.Assert.assertSame; 023 import static org.junit.Assert.assertTrue; 024 025 import java.util.HashMap; 026 import java.util.Map; 027 028 import org.apache.commons.configuration.ConfigurationRuntimeException; 029 import org.junit.After; 030 import org.junit.Before; 031 import org.junit.Test; 032 033 /** 034 * Test class for BeanHelper. 035 * 036 * @since 1.3 037 * @author <a 038 * href="http://commons.apache.org/configuration/team-list.html">Commons 039 * Configuration team</a> 040 * @version $Id: TestBeanHelper.java 1225344 2011-12-28 21:28:23Z oheger $ 041 */ 042 public class TestBeanHelper 043 { 044 /** Constant for the name of the test bean factory. */ 045 private static final String TEST_FACTORY = "testFactory"; 046 047 /** 048 * Stores the default bean factory. Because this is a static field in 049 * BeanHelper it is temporarily stored and reset after the tests. 050 */ 051 private BeanFactory tempDefaultBeanFactory; 052 053 @Before 054 public void setUp() throws Exception 055 { 056 tempDefaultBeanFactory = BeanHelper.getDefaultBeanFactory(); 057 deregisterFactories(); 058 } 059 060 @After 061 public void tearDown() throws Exception 062 { 063 deregisterFactories(); 064 065 // Reset old default bean factory 066 BeanHelper.setDefaultBeanFactory(tempDefaultBeanFactory); 067 } 068 069 /** 070 * Removes all bean factories that might have been registered during a test. 071 */ 072 private void deregisterFactories() 073 { 074 for (String name : BeanHelper.registeredFactoryNames()) 075 { 076 BeanHelper.deregisterBeanFactory(name); 077 } 078 assertTrue("Remaining registered bean factories", BeanHelper 079 .registeredFactoryNames().isEmpty()); 080 } 081 082 /** 083 * Tests registering a new bean factory. 084 */ 085 @Test 086 public void testRegisterBeanFactory() 087 { 088 assertTrue("List of registered factories is not empty", BeanHelper 089 .registeredFactoryNames().isEmpty()); 090 BeanHelper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory()); 091 assertEquals("Wrong number of registered factories", 1, BeanHelper 092 .registeredFactoryNames().size()); 093 assertTrue("Test factory is not contained", BeanHelper 094 .registeredFactoryNames().contains(TEST_FACTORY)); 095 } 096 097 /** 098 * Tries to register a null factory. This should cause an exception. 099 */ 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 }