blob: 311d622f7b4d082c66bed9298d2fe2e261603969 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.configuration2.beanutils;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.LazyDynaBean;
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
/**
* Test class for BeanHelper.
*
* @since 1.3
*/
public class TestBeanHelper
{
/** Constant for the test value of the string property. */
private static final String TEST_STRING = "testString";
/** Constant for the test value of the numeric property. */
private static final int TEST_INT = 42;
/** Constant for the name of the test bean factory. */
private static final String TEST_FACTORY = "testFactory";
/** The test bean helper instance. */
private BeanHelper helper;
@Before
public void setUp() throws Exception
{
helper = new BeanHelper(new TestBeanFactory());
}
/**
* Tests whether the correct default bean factory is set.
*/
@Test
public void testDefaultBeanFactory()
{
helper = new BeanHelper();
assertSame("Wrong default bean factory", DefaultBeanFactory.INSTANCE,
helper.getDefaultBeanFactory());
}
/**
* Tests whether a specific default bean factory can be set when
* constructing an instance.
*/
@Test
public void testInitWithBeanFactory()
{
final BeanFactory factory = EasyMock.createMock(BeanFactory.class);
EasyMock.replay(factory);
helper = new BeanHelper(factory);
assertSame("Wrong default bean factory", factory,
helper.getDefaultBeanFactory());
}
/**
* Tests the default instance of BeanHelper.
*/
@Test
public void testDefaultInstance()
{
assertSame("Wrong factory for default instance",
DefaultBeanFactory.INSTANCE,
BeanHelper.INSTANCE.getDefaultBeanFactory());
}
/**
* Tests that a newly created instance does not have any bean factories
* registered.
*/
@Test
public void testRegisteredFactoriesEmptyForNewInstance()
{
assertTrue("List of registered factories is not empty", helper
.registeredFactoryNames().isEmpty());
}
/**
* Tests registering a new bean factory.
*/
@Test
public void testRegisterBeanFactory()
{
helper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory());
assertEquals("Wrong number of registered factories", 1, helper
.registeredFactoryNames().size());
assertTrue("Test factory is not contained", helper
.registeredFactoryNames().contains(TEST_FACTORY));
}
/**
* Tries to register a null factory. This should cause an exception.
*/
@Test(expected = IllegalArgumentException.class)
public void testRegisterBeanFactoryNull()
{
helper.registerBeanFactory(TEST_FACTORY, null);
}
/**
* Tries to register a bean factory with a null name. This should cause an
* exception.
*/
@Test(expected = IllegalArgumentException.class)
public void testRegisterBeanFactoryNullName()
{
helper.registerBeanFactory(null, new TestBeanFactory());
}
/**
* Tests to deregister a bean factory.
*/
@Test
public void testDeregisterBeanFactory()
{
final BeanFactory factory = new TestBeanFactory();
helper.registerBeanFactory(TEST_FACTORY, factory);
assertSame("Could not deregister factory", factory, helper
.deregisterBeanFactory(TEST_FACTORY));
assertTrue("List of factories is not empty", helper
.registeredFactoryNames().isEmpty());
}
/**
* Tests deregisterBeanFactory() for a non-existing factory name.
*/
@Test
public void testDeregisterBeanFactoryNonExisting()
{
assertNull("deregistering non existing factory",
helper.deregisterBeanFactory(TEST_FACTORY));
}
/**
* Tests deregisterBeanFactory() for a null factory name.
*/
@Test
public void testDeregisterBeanFactoryNull() {
assertNull("deregistering null factory",
helper.deregisterBeanFactory(null));
}
/**
* Tests initializing a bean.
*/
@Test
public void testInitBean()
{
final BeanDeclarationTestImpl data = setUpBeanDeclaration();
final BeanCreationTestBean bean = new BeanCreationTestBean();
helper.initBean(bean, data);
checkBean(bean);
}
/**
* Tests initializing a bean when the bean declaration does not contain any
* data.
*/
@Test
public void testInitBeanWithNoData()
{
final BeanDeclarationTestImpl data = new BeanDeclarationTestImpl();
final BeanCreationTestBean bean = new BeanCreationTestBean();
helper.initBean(bean, data);
assertNull("Wrong string property", bean.getStringValue());
assertEquals("Wrong int property", 0, bean.getIntValue());
assertNull("Buddy was set", bean.getBuddy());
}
/**
* Tries to initialize a bean with a bean declaration that contains an
* invalid property value. This should cause an exception.
*/
@Test(expected = ConfigurationRuntimeException.class)
public void testInitBeanWithInvalidProperty()
{
final BeanDeclarationTestImpl data = setUpBeanDeclaration();
data.getBeanProperties().put("nonExistingProperty", Boolean.TRUE);
helper.initBean(new BeanCreationTestBean(), data);
}
/**
* Tests creating a bean. All necessary information is stored in the bean
* declaration.
*/
@Test
public void testCreateBean()
{
final TestBeanFactory factory = new TestBeanFactory();
helper.registerBeanFactory(TEST_FACTORY, factory);
final BeanDeclarationTestImpl data = setUpBeanDeclaration();
data.setBeanFactoryName(TEST_FACTORY);
data.setBeanClassName(BeanCreationTestBean.class.getName());
checkBean((BeanCreationTestBean) helper.createBean(data, null));
assertNull("A parameter was passed", factory.parameter);
assertEquals("Factory not called", 1, factory.getCreateBeanCount());
}
/**
* Tests whether a bean with a property of type collection can be created.
*/
@Test
public void testCreateBeanWithListChildBean()
{
final TestBeanFactory factory = new TestBeanFactory();
helper.registerBeanFactory(TEST_FACTORY, factory);
final BeanDeclarationTestImpl data = setUpBeanDeclarationWithListChild();
data.setBeanFactoryName(TEST_FACTORY);
data.setBeanClassName(BeanCreationTestBeanWithListChild.class.getName());
checkBean((BeanCreationTestBeanWithListChild) helper.createBean(data, null));
assertNull("A parameter was passed", factory.parameter);
assertEquals("Factory not called", 1, factory.getCreateBeanCount());
}
/**
* Tests creating a bean when no bean declaration is provided. This should
* cause an exception.
*/
@Test(expected = IllegalArgumentException.class)
public void testCreateBeanWithNullDeclaration()
{
helper.createBean(null);
}
/**
* Tests creating a bean. The bean's class is specified as the default class
* argument.
*/
@Test
public void testCreateBeanWithDefaultClass()
{
helper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory());
final BeanDeclarationTestImpl data = setUpBeanDeclaration();
data.setBeanFactoryName(TEST_FACTORY);
checkBean((BeanCreationTestBean) helper.createBean(data, BeanCreationTestBean.class));
}
/**
* Tests creating a bean when the bean's class is specified as the default
* class of the bean factory.
*/
@Test
public void testCreateBeanWithFactoryDefaultClass()
{
final TestBeanFactory factory = new TestBeanFactory();
factory.supportsDefaultClass = true;
helper.registerBeanFactory(TEST_FACTORY, factory);
final BeanDeclarationTestImpl data = setUpBeanDeclaration();
data.setBeanFactoryName(TEST_FACTORY);
checkBean((BeanCreationTestBean) helper.createBean(data, null));
assertEquals("Factory not called", 1, factory.getCreateBeanCount());
}
/**
* Tries to create a bean if no class is provided. This should cause an
* exception.
*/
@Test(expected = ConfigurationRuntimeException.class)
public void testCreateBeanWithNoClass()
{
helper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory());
final BeanDeclarationTestImpl data = setUpBeanDeclaration();
data.setBeanFactoryName(TEST_FACTORY);
helper.createBean(data, null);
}
/**
* Tries to create a bean with a non existing class. This should cause an
* exception.
*/
@Test(expected = ConfigurationRuntimeException.class)
public void testCreateBeanWithInvalidClass()
{
helper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory());
final BeanDeclarationTestImpl data = setUpBeanDeclaration();
data.setBeanFactoryName(TEST_FACTORY);
data.setBeanClassName("non.existing.ClassName");
helper.createBean(data, null);
}
/**
* Tests creating a bean using the default bean factory.
*/
@Test
public void testCreateBeanWithDefaultFactory()
{
final BeanDeclarationTestImpl data = setUpBeanDeclaration();
data.setBeanClassName(BeanCreationTestBean.class.getName());
checkBean((BeanCreationTestBean) helper.createBean(data, null));
final TestBeanFactory factory = (TestBeanFactory) helper.getDefaultBeanFactory();
assertTrue("Factory not called", factory.getCreateBeanCount() > 0);
}
/**
* Tests creating a bean using a non registered factory.
*/
@Test(expected = ConfigurationRuntimeException.class)
public void testCreateBeanWithUnknownFactory()
{
final BeanDeclarationTestImpl data = setUpBeanDeclaration();
data.setBeanFactoryName(TEST_FACTORY);
data.setBeanClassName(BeanCreationTestBean.class.getName());
helper.createBean(data, null);
}
/**
* Tests creating a bean when the factory throws an exception.
*/
@Test(expected = ConfigurationRuntimeException.class)
public void testCreateBeanWithException()
{
helper.registerBeanFactory(TEST_FACTORY, new TestBeanFactory());
final BeanDeclarationTestImpl data = setUpBeanDeclaration();
data.setBeanFactoryName(TEST_FACTORY);
data.setBeanClassName(getClass().getName());
helper.createBean(data, null);
}
/**
* Tests if a parameter is correctly passed to the bean factory.
*/
@Test
public void testCreateBeanWithParameter()
{
final Object param = Integer.valueOf(42);
final TestBeanFactory factory = new TestBeanFactory();
helper.registerBeanFactory(TEST_FACTORY, factory);
final BeanDeclarationTestImpl data = setUpBeanDeclaration();
data.setBeanFactoryName(TEST_FACTORY);
data.setBeanClassName(BeanCreationTestBean.class.getName());
checkBean((BeanCreationTestBean) helper.createBean(data, null, param));
assertSame("Wrong parameter", param, factory.parameter);
}
/**
* Tests whether a wrapper DynaBean for a Java bean can be created.
*/
@Test
public void testCreateWrapDynaBean()
{
final PropertiesConfiguration config = new PropertiesConfiguration();
final DynaBean bean = BeanHelper.createWrapDynaBean(config);
final String value = "TestFooter";
bean.set("footer", value);
assertEquals("Property not set", value, config.getFooter());
}
/**
* Tries to create a wrapper DynaBean for a null bean.
*/
@Test(expected = IllegalArgumentException.class)
public void testCreateWrapDynaBeanNull()
{
BeanHelper.createWrapDynaBean(null);
}
/**
* Tests whether properties from one bean to another can be copied.
*/
@Test
public void testCopyProperties() throws Exception
{
final PropertiesConfiguration src = new PropertiesConfiguration();
src.setHeader("TestHeader");
src.setFooter("TestFooter");
final LazyDynaBean dest = new LazyDynaBean();
BeanHelper.copyProperties(dest, src);
assertEquals("Wrong footer property", "TestFooter", dest.get("footer"));
assertEquals("Wrong header property", "TestHeader", dest.get("header"));
}
/**
* Returns an initialized bean declaration.
*
* @return the bean declaration
*/
private BeanDeclarationTestImpl setUpBeanDeclaration()
{
final BeanDeclarationTestImpl data = new BeanDeclarationTestImpl();
final Map<String, Object> properties = new HashMap<>();
properties.put("stringValue", TEST_STRING);
properties.put("intValue", String.valueOf(TEST_INT));
data.setBeanProperties(properties);
final BeanDeclarationTestImpl buddyData = new BeanDeclarationTestImpl();
final Map<String, Object> properties2 = new HashMap<>();
properties2.put("stringValue", "Another test string");
properties2.put("intValue", Integer.valueOf(100));
buddyData.setBeanProperties(properties2);
buddyData.setBeanClassName(BeanCreationTestBean.class.getName());
final Map<String, Object> nested = new HashMap<>();
nested.put("buddy", buddyData);
data.setNestedBeanDeclarations(nested);
return data;
}
/**
* Same as setUpBeanDeclaration, but returns a nested array of beans
* as a single property. Tests multi-value (Collection<BeanDeclaration>)
* children construction.
*
* @return The bean declaration with a list child bean proerty
*/
private BeanDeclarationTestImpl setUpBeanDeclarationWithListChild()
{
final BeanDeclarationTestImpl data = new BeanDeclarationTestImpl();
final Map<String, Object> properties = new HashMap<>();
properties.put("stringValue", TEST_STRING);
properties.put("intValue", String.valueOf(TEST_INT));
data.setBeanProperties(properties);
final List<BeanDeclaration> childData = new ArrayList<>();
childData.add(createChildBean("child1"));
childData.add(createChildBean("child2"));
final Map<String, Object> nested = new HashMap<>();
nested.put("children", childData);
data.setNestedBeanDeclarations(nested);
return data;
}
/**
* Create a simple bean declaration that has no children for testing
* of nested children bean declarations.
*
* @param name A name prefix that can be used to disambiguate the children
* @return A simple declaration
*/
private BeanDeclarationTestImpl createChildBean(final String name)
{
final BeanDeclarationTestImpl childBean = new BeanDeclarationTestImpl();
final Map<String, Object> properties2 = new HashMap<>();
properties2.put("stringValue", name + " Another test string");
properties2.put("intValue", Integer.valueOf(100));
childBean.setBeanProperties(properties2);
childBean.setBeanClassName(BeanCreationTestBean.class.getName());
return childBean;
}
/**
* Tests if the bean was correctly initialized from the data of the test
* bean declaration.
*
* @param bean the bean to be checked
*/
private void checkBean(final BeanCreationTestBean bean)
{
assertEquals("Wrong string property", TEST_STRING, bean
.getStringValue());
assertEquals("Wrong int property", TEST_INT, bean.getIntValue());
final BeanCreationTestBean buddy = bean.getBuddy();
assertNotNull("Buddy was not set", buddy);
assertEquals("Wrong string property in buddy", "Another test string",
buddy.getStringValue());
assertEquals("Wrong int property in buddy", 100, buddy.getIntValue());
}
/**
* Tests if the bean was correctly initialized from the data of the test
* bean declaration.
*
* @param bean the bean to be checked
*/
private void checkBean(final BeanCreationTestBeanWithListChild bean)
{
assertEquals("Wrong string property", TEST_STRING, bean
.getStringValue());
assertEquals("Wrong int property", TEST_INT, bean.getIntValue());
final List<BeanCreationTestBean> children = bean.getChildren();
assertNotNull("Children were not set", children);
assertEquals("Wrong number of children created", children.size(), 2);
assertNotNull("First child was set as null", children.get(0));
assertNotNull("Second child was set as null", children.get(1));
}
/**
* An implementation of the BeanFactory interface used for testing. This
* implementation is really simple: If the BeanCreationTestBean class is provided, a new
* instance will be created. Otherwise an exception is thrown.
*/
private class TestBeanFactory implements BeanFactory
{
Object parameter;
boolean supportsDefaultClass;
/** A counter for the created instances. */
private int createBeanCount;
@Override
public Object createBean(final BeanCreationContext bcc) throws Exception
{
createBeanCount++;
parameter = bcc.getParameter();
if (BeanCreationTestBean.class.equals(bcc.getBeanClass()))
{
final BeanCreationTestBean bean = new BeanCreationTestBean();
helper.initBean(bean, bcc.getBeanDeclaration());
return bean;
}
if (BeanCreationTestBeanWithListChild.class.equals(bcc
.getBeanClass()))
{
final BeanCreationTestBeanWithListChild bean =
new BeanCreationTestBeanWithListChild();
helper.initBean(bean, bcc.getBeanDeclaration());
return bean;
}
throw new IllegalArgumentException("Unsupported class: "
+ bcc.getBeanClass());
}
/**
* Returns the default class, but only if the supportsDefaultClass flag
* is set.
*/
@Override
public Class<?> getDefaultBeanClass()
{
return supportsDefaultClass ? BeanCreationTestBean.class : null;
}
/**
* Returns the number of beans created via this factory.
*
* @return the number of created beans
*/
public int getCreateBeanCount()
{
return createBeanCount;
}
}
}