blob: 357f220eed461ceec38025ec9c2429f343f09af0 [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.beanutils2;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.beanutils2.priv.PrivateBeanFactory;
import org.apache.commons.beanutils2.priv.PrivateDirect;
import org.apache.commons.beanutils2.priv.PublicSubBean;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* <p>
* Test Case for the PropertyUtils class. The majority of these tests use instances of the TestBean class, so be sure to update the tests if you change the
* characteristics of that class.
* </p>
*
* <p>
* So far, this test case has tests for the following methods of the {@code PropertyUtils} class:
* </p>
* <ul>
* <li>getIndexedProperty(Object,String)</li>
* <li>getIndexedProperty(Object,String,int)</li>
* <li>getMappedProperty(Object,String)</li>
* <li>getMappedProperty(Object,String,String</li>
* <li>getNestedProperty(Object,String)</li>
* <li>getPropertyDescriptor(Object,String)</li>
* <li>getPropertyDescriptors(Object)</li>
* <li>getPropertyType(Object,String)</li>
* <li>getSimpleProperty(Object,String)</li>
* <li>setIndexedProperty(Object,String,Object)</li>
* <li>setIndexedProperty(Object,String,String,Object)</li>
* <li>setMappedProperty(Object,String,Object)</li>
* <li>setMappedProperty(Object,String,String,Object)</li>
* <li>setNestedProperty(Object,String,Object)</li>
* <li>setSimpleProperty(Object,String,Object)</li>
* </ul>
*
*/
public class PropertyUtilsTestCase extends TestCase {
/**
* The fully qualified class name of our private directly implemented interface.
*/
private static final String PRIVATE_DIRECT_CLASS = "org.apache.commons.beanutils2.priv.PrivateDirect";
/**
* The fully qualified class name of our private indirectly implemented interface.
*/
private static final String PRIVATE_INDIRECT_CLASS = "org.apache.commons.beanutils2.priv.PrivateIndirect";
/**
* The fully qualified class name of our test bean class.
*/
private static final String TEST_BEAN_CLASS = "org.apache.commons.beanutils2.TestBean";
/**
* The set of property names we expect to have returned when calling {@code getPropertyDescriptors()}. You should update this list when new properties are
* added to TestBean.
*/
protected final static String[] properties = { "booleanProperty", "booleanSecond", "doubleProperty", "dupProperty", "floatProperty", "intArray",
"intIndexed", "intProperty", "listIndexed", "longProperty", "nested", "nullProperty", "readOnlyProperty", "shortProperty", "stringArray",
"stringIndexed", "stringProperty", "writeOnlyProperty", };
/**
* Finds the descriptor of the name property.
*
* @param desc the array with descriptors
* @return the found descriptor or null
*/
private static PropertyDescriptor findNameDescriptor(final PropertyDescriptor[] desc) {
for (final PropertyDescriptor element : desc) {
if (element.getName().equals("name")) {
return element;
}
}
return null;
}
/**
* Creates the tests included in this test suite.
*/
public static Test suite() {
return new TestSuite(PropertyUtilsTestCase.class);
}
/**
* The basic test bean for each test.
*/
protected TestBean bean = null;
/**
* The "package private subclass" test bean for each test.
*/
protected TestBeanPackageSubclass beanPackageSubclass = null;
/**
* The test bean for private access tests.
*/
protected PrivateDirect beanPrivate = null;
/**
* The test bean for private access tests of subclasses.
*/
protected PrivateDirect beanPrivateSubclass = null;
/**
* The "public subclass" test bean for each test.
*/
protected TestBeanPublicSubclass beanPublicSubclass = null;
/**
* The set of properties that should be described.
*/
protected String[] describes = { "booleanProperty", "booleanSecond", "doubleProperty", "floatProperty", "intArray",
// "intIndexed",
"intProperty", "listIndexed", "longProperty",
// "mappedObjects",
// "mappedProperty",
// "mappedIntProperty",
"nested", "nullProperty",
// "readOnlyProperty",
"shortProperty", "stringArray",
// "stringIndexed",
"stringProperty" };
/**
* Constructs a new instance of this test case.
*
* @param name Name of the test case
*/
public PropertyUtilsTestCase(final String name) {
super(name);
}
/**
* Returns a single string containing all the keys in the map, sorted in alphabetical order and separated by ", ".
* <p>
* If there are no keys, an empty string is returned.
*/
private String keysToString(final Map<?, ?> map) {
final Object[] mapKeys = map.keySet().toArray();
java.util.Arrays.sort(mapKeys);
final StringBuilder buf = new StringBuilder();
for (int i = 0; i < mapKeys.length; ++i) {
if (i != 0) {
buf.append(", ");
}
buf.append(mapKeys[i]);
}
return buf.toString();
}
/**
* Sets up instance variables required by this test case.
*/
@Override
public void setUp() {
bean = new TestBean();
beanPackageSubclass = new TestBeanPackageSubclass();
beanPrivate = PrivateBeanFactory.create();
beanPrivateSubclass = PrivateBeanFactory.createSubclass();
beanPublicSubclass = new TestBeanPublicSubclass();
final DynaProperty[] properties = { new DynaProperty("stringProperty", String.class), new DynaProperty("nestedBean", TestBean.class),
new DynaProperty("nullDynaBean", DynaBean.class) };
final BasicDynaClass dynaClass = new BasicDynaClass("nestedDynaBean", BasicDynaBean.class, properties);
final BasicDynaBean nestedDynaBean = new BasicDynaBean(dynaClass);
nestedDynaBean.set("nestedBean", bean);
bean.setNestedDynaBean(nestedDynaBean);
PropertyUtils.clearDescriptors();
}
/**
* Tear down instance variables required by this test case.
*/
@Override
public void tearDown() {
bean = null;
beanPackageSubclass = null;
beanPrivate = null;
beanPrivateSubclass = null;
beanPublicSubclass = null;
PropertyUtils.resetBeanIntrospectors();
}
/**
* Tries to add a null BeanIntrospector.
*/
public void testAddBeanIntrospectorNull() {
try {
PropertyUtils.addBeanIntrospector(null);
fail("Could add null BeanIntrospector!");
} catch (final IllegalArgumentException iex) {
// ok
}
}
/**
* Test copyProperties() when the origin is a {@code Map}.
*/
public void testCopyPropertiesMap() {
final Map<String, Object> map = new HashMap<>();
map.put("booleanProperty", Boolean.FALSE);
map.put("doubleProperty", Double.valueOf(333.0));
map.put("dupProperty", new String[] { "New 0", "New 1", "New 2" });
map.put("floatProperty", Float.valueOf((float) 222.0));
map.put("intArray", new int[] { 0, 100, 200 });
map.put("intProperty", Integer.valueOf(111));
map.put("longProperty", Long.valueOf(444));
map.put("shortProperty", Short.valueOf((short) 555));
map.put("stringProperty", "New String Property");
try {
PropertyUtils.copyProperties(bean, map);
} catch (final Throwable t) {
fail("Threw " + t.toString());
}
// Scalar properties
assertEquals("booleanProperty", false, bean.getBooleanProperty());
assertEquals("doubleProperty", 333.0, bean.getDoubleProperty(), 0.005);
assertEquals("floatProperty", (float) 222.0, bean.getFloatProperty(), (float) 0.005);
assertEquals("intProperty", 111, bean.getIntProperty());
assertEquals("longProperty", 444, bean.getLongProperty());
assertEquals("shortProperty", (short) 555, bean.getShortProperty());
assertEquals("stringProperty", "New String Property", bean.getStringProperty());
// Indexed Properties
final String[] dupProperty = bean.getDupProperty();
assertNotNull("dupProperty present", dupProperty);
assertEquals("dupProperty length", 3, dupProperty.length);
assertEquals("dupProperty[0]", "New 0", dupProperty[0]);
assertEquals("dupProperty[1]", "New 1", dupProperty[1]);
assertEquals("dupProperty[2]", "New 2", dupProperty[2]);
final int[] intArray = bean.getIntArray();
assertNotNull("intArray present", intArray);
assertEquals("intArray length", 3, intArray.length);
assertEquals("intArray[0]", 0, intArray[0]);
assertEquals("intArray[1]", 100, intArray[1]);
assertEquals("intArray[2]", 200, intArray[2]);
}
/**
* Tests whether the default introspection mechanism can be replaced by a custom BeanIntrospector.
*/
public void testCustomIntrospection() {
final PropertyDescriptor[] desc1 = PropertyUtils.getPropertyDescriptors(AlphaBean.class);
PropertyDescriptor nameDescriptor = findNameDescriptor(desc1);
assertNotNull("No write method", nameDescriptor.getWriteMethod());
final BeanIntrospector bi = icontext -> {
final Set<String> names = icontext.propertyNames();
final PropertyDescriptor[] newDescs = new PropertyDescriptor[names.size()];
int idx = 0;
for (final Iterator<String> it = names.iterator(); it.hasNext(); idx++) {
final String propName = it.next();
final PropertyDescriptor pd = icontext.getPropertyDescriptor(propName);
newDescs[idx] = new PropertyDescriptor(pd.getName(), pd.getReadMethod(), null);
}
icontext.addPropertyDescriptors(newDescs);
};
PropertyUtils.clearDescriptors();
PropertyUtils.addBeanIntrospector(bi);
final PropertyDescriptor[] desc2 = PropertyUtils.getPropertyDescriptors(AlphaBean.class);
assertEquals("Different number of properties", desc1.length, desc2.length);
nameDescriptor = findNameDescriptor(desc2);
assertNull("Got a write method", nameDescriptor.getWriteMethod());
PropertyUtils.removeBeanIntrospector(bi);
}
/**
* Tests whether exceptions during custom introspection are handled.
*/
public void testCustomIntrospectionEx() {
final BeanIntrospector bi = icontext -> {
throw new IntrospectionException("TestException");
};
PropertyUtils.clearDescriptors();
PropertyUtils.addBeanIntrospector(bi);
final PropertyDescriptor[] desc = PropertyUtils.getPropertyDescriptors(AlphaBean.class);
assertNotNull("Introspection did not work", findNameDescriptor(desc));
PropertyUtils.removeBeanIntrospector(bi);
}
/**
* Test the describe() method.
*/
public void testDescribe() {
Map<String, Object> map = null;
try {
map = PropertyUtils.describe(bean);
} catch (final Exception e) {
fail("Threw exception " + e);
}
// Verify existence of all the properties that should be present
for (final String describe : describes) {
assertTrue("Property '" + describe + "' is present", map.containsKey(describe));
}
assertTrue("Property 'writeOnlyProperty' is not present", !map.containsKey("writeOnlyProperty"));
// Verify the values of scalar properties
assertEquals("Value of 'booleanProperty'", Boolean.TRUE, map.get("booleanProperty"));
assertEquals("Value of 'doubleProperty'", Double.valueOf(321.0), map.get("doubleProperty"));
assertEquals("Value of 'floatProperty'", Float.valueOf((float) 123.0), map.get("floatProperty"));
assertEquals("Value of 'intProperty'", Integer.valueOf(123), map.get("intProperty"));
assertEquals("Value of 'longProperty'", Long.valueOf(321), map.get("longProperty"));
assertEquals("Value of 'shortProperty'", Short.valueOf((short) 987), map.get("shortProperty"));
assertEquals("Value of 'stringProperty'", "This is a string", (String) map.get("stringProperty"));
}
/**
* Test {@link PropertyUtilsBean}'s invoke method throwing an IllegalArgumentException and check that the "cause" has been properly initialized for JDK 1.4+
* See BEANUTILS-266 for changes and reason for test
*/
public void testExceptionFromInvoke() throws Exception {
if (BeanUtilsBeanTestCase.isPre14JVM()) {
return;
}
try {
PropertyUtils.setSimpleProperty(bean, "intProperty", "XXX");
} catch (final IllegalArgumentException t) {
final Throwable cause = (Throwable) PropertyUtils.getProperty(t, "cause");
assertNotNull("Cause not found", cause);
assertTrue("Expected cause to be IllegalArgumentException, but was: " + cause.getClass(), cause instanceof IllegalArgumentException);
// JDK 1.6 doesn't have "argument type mismatch" message
// assertEquals("Check error message", "argument type mismatch", cause.getMessage());
} catch (final Throwable t) {
fail("Expected IllegalArgumentException, but threw " + t);
}
}
/**
* Corner cases on getPropertyDescriptor invalid arguments.
*/
public void testGetDescriptorArguments() {
try {
PropertyUtils.getPropertyDescriptor(null, "stringProperty");
fail("Should throw IllegalArgumentException 1");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 1");
}
try {
PropertyUtils.getPropertyDescriptor(bean, null);
fail("Should throw IllegalArgumentException 2");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 2");
}
}
/**
* Base for testGetDescriptorXxxxx() series of tests.
*
* @param name Name of the property to be retrieved
* @param read Expected name of the read method (or null)
* @param write Expected name of the write method (or null)
*/
protected void testGetDescriptorBase(final String name, final String read, final String write) {
try {
final PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor(bean, name);
if (read == null && write == null) {
assertNull("Got descriptor", pd);
return;
}
assertNotNull("Got descriptor", pd);
final Method rm = pd.getReadMethod();
if (read != null) {
assertNotNull("Got read method", rm);
assertEquals("Got correct read method", rm.getName(), read);
} else {
assertNull("Got read method", rm);
}
final Method wm = pd.getWriteMethod();
if (write != null) {
assertNotNull("Got write method", wm);
assertEquals("Got correct write method", wm.getName(), write);
} else {
assertNull("Got write method", wm);
}
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Positive getPropertyDescriptor on property {@code booleanProperty}.
*/
public void testGetDescriptorBoolean() {
testGetDescriptorBase("booleanProperty", "getBooleanProperty", "setBooleanProperty");
}
/**
* Positive getPropertyDescriptor on property {@code doubleProperty}.
*/
public void testGetDescriptorDouble() {
testGetDescriptorBase("doubleProperty", "getDoubleProperty", "setDoubleProperty");
}
/**
* Positive getPropertyDescriptor on property {@code floatProperty}.
*/
public void testGetDescriptorFloat() {
testGetDescriptorBase("floatProperty", "getFloatProperty", "setFloatProperty");
}
/**
* Positive getPropertyDescriptor on property {@code intProperty}.
*/
public void testGetDescriptorInt() {
testGetDescriptorBase("intProperty", "getIntProperty", "setIntProperty");
}
/**
* <p>
* Negative tests on an invalid property with two different boolean getters (which is fine, according to the JavaBeans spec) but a String setter instead of
* a boolean setter.
* </p>
*
* <p>
* Although one could logically argue that this combination of method signatures should not identify a property at all, there is a sentence in Section 8.3.1
* making it clear that the behavior tested for here is correct: "If we find only one of these methods, then we regard it as defining either a read-only or
* write-only property called <em>&lt;property-name&gt;</em>.
* </p>
*/
public void testGetDescriptorInvalidBoolean() throws Exception {
final PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor(bean, "invalidBoolean");
assertNotNull("invalidBoolean is a property", pd);
assertNotNull("invalidBoolean has a getter method", pd.getReadMethod());
assertNull("invalidBoolean has no write method", pd.getWriteMethod());
assertTrue("invalidBoolean getter method is isInvalidBoolean or getInvalidBoolean",
Arrays.asList("isInvalidBoolean", "getInvalidBoolean").contains(pd.getReadMethod().getName()));
}
/**
* Positive getPropertyDescriptor on property {@code longProperty}.
*/
public void testGetDescriptorLong() {
testGetDescriptorBase("longProperty", "getLongProperty", "setLongProperty");
}
/**
* Test getting mapped descriptor with periods in the key.
*/
public void testGetDescriptorMappedPeriods() {
bean.getMappedIntProperty("xyz"); // initializes mappedIntProperty
PropertyDescriptor desc;
final Integer testIntegerValue = Integer.valueOf(1234);
bean.setMappedIntProperty("key.with.a.dot", testIntegerValue.intValue());
assertEquals("Can retrieve directly", testIntegerValue, Integer.valueOf(bean.getMappedIntProperty("key.with.a.dot")));
try {
desc = PropertyUtils.getPropertyDescriptor(bean, "mappedIntProperty(key.with.a.dot)");
assertEquals("Check descriptor type (A)", Integer.TYPE, ((MappedPropertyDescriptor) desc).getMappedPropertyType());
} catch (final Exception e) {
fail("Threw exception (A): " + e);
}
bean.setMappedObjects("nested.property", new TestBean(testIntegerValue.intValue()));
assertEquals("Can retrieve directly", testIntegerValue, Integer.valueOf(((TestBean) bean.getMappedObjects("nested.property")).getIntProperty()));
try {
desc = PropertyUtils.getPropertyDescriptor(bean, "mappedObjects(nested.property).intProperty");
assertEquals("Check descriptor type (B)", Integer.TYPE, desc.getPropertyType());
} catch (final Exception e) {
fail("Threw exception (B): " + e);
}
}
/**
* Positive getPropertyDescriptor on property {@code readOnlyProperty}.
*/
public void testGetDescriptorReadOnly() {
testGetDescriptorBase("readOnlyProperty", "getReadOnlyProperty", null);
}
/**
* Positive test for getPropertyDescriptors(). Each property name listed in {@code properties} should be returned exactly once.
*/
public void testGetDescriptors() {
final PropertyDescriptor[] pd = PropertyUtils.getPropertyDescriptors(bean);
assertNotNull("Got descriptors", pd);
final int[] count = new int[properties.length];
for (final PropertyDescriptor element : pd) {
final String name = element.getName();
for (int j = 0; j < properties.length; j++) {
if (name.equals(properties[j])) {
count[j]++;
}
}
}
for (int j = 0; j < properties.length; j++) {
if (count[j] < 0) {
fail("Missing property " + properties[j]);
} else if (count[j] > 1) {
fail("Duplicate property " + properties[j]);
}
}
}
/**
* Corner cases on getPropertyDescriptors invalid arguments.
*/
public void testGetDescriptorsArguments() {
try {
PropertyUtils.getPropertyDescriptors(null);
fail("Should throw IllegalArgumentException");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException");
}
}
/**
* Positive getPropertyDescriptor on property {@code booleanSecond} that uses an "is" method as the getter.
*/
public void testGetDescriptorSecond() {
testGetDescriptorBase("booleanSecond", "isBooleanSecond", "setBooleanSecond");
}
/**
* Positive getPropertyDescriptor on property {@code shortProperty}.
*/
public void testGetDescriptorShort() {
testGetDescriptorBase("shortProperty", "getShortProperty", "setShortProperty");
}
/**
* Positive getPropertyDescriptor on property {@code stringProperty}.
*/
public void testGetDescriptorString() {
testGetDescriptorBase("stringProperty", "getStringProperty", "setStringProperty");
}
/**
* Negative getPropertyDescriptor on property {@code unknown}.
*/
public void testGetDescriptorUnknown() {
testGetDescriptorBase("unknown", null, null);
}
/**
* Positive getPropertyDescriptor on property {@code writeOnlyProperty}.
*/
public void testGetDescriptorWriteOnly() {
testGetDescriptorBase("writeOnlyProperty", null, "setWriteOnlyProperty");
}
/**
* Corner cases on getIndexedProperty invalid arguments.
*/
public void testGetIndexedArguments() {
// Use explicit index argument
try {
PropertyUtils.getIndexedProperty(null, "intArray", 0);
fail("Should throw IllegalArgumentException 1");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 1");
}
try {
PropertyUtils.getIndexedProperty(bean, null, 0);
fail("Should throw IllegalArgumentException 2");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 2");
}
// Use index expression
try {
PropertyUtils.getIndexedProperty(null, "intArray[0]");
fail("Should throw IllegalArgumentException 3");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 3");
}
try {
PropertyUtils.getIndexedProperty(bean, "[0]");
fail("Should throw NoSuchMethodException 4");
} catch (final NoSuchMethodException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of NoSuchMethodException 4");
}
try {
PropertyUtils.getIndexedProperty(bean, "intArray");
fail("Should throw IllegalArgumentException 5");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 5");
}
// Use explicit index argument
try {
PropertyUtils.getIndexedProperty(null, "intIndexed", 0);
fail("Should throw IllegalArgumentException 1");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 1");
}
try {
PropertyUtils.getIndexedProperty(bean, null, 0);
fail("Should throw IllegalArgumentException 2");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 2");
}
// Use index expression
try {
PropertyUtils.getIndexedProperty(null, "intIndexed[0]");
fail("Should throw IllegalArgumentException 3");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 3");
}
try {
PropertyUtils.getIndexedProperty(bean, "[0]");
fail("Should throw NoSuchMethodException 4");
} catch (final NoSuchMethodException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of NoSuchMethodException 4");
}
try {
PropertyUtils.getIndexedProperty(bean, "intIndexed");
fail("Should throw IllegalArgumentException 5");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 5");
}
}
/**
* Test getting an indexed value out of a multi-dimensional array
*/
public void testGetIndexedArray() {
final String[] firstArray = { "FIRST-1", "FIRST-2", "FIRST-3" };
final String[] secondArray = { "SECOND-1", "SECOND-2", "SECOND-3", "SECOND-4" };
final String[][] mainArray = { firstArray, secondArray };
final TestBean bean = new TestBean(mainArray);
try {
assertEquals("firstArray[0]", firstArray[0], PropertyUtils.getProperty(bean, "string2dArray[0][0]"));
assertEquals("firstArray[1]", firstArray[1], PropertyUtils.getProperty(bean, "string2dArray[0][1]"));
assertEquals("firstArray[2]", firstArray[2], PropertyUtils.getProperty(bean, "string2dArray[0][2]"));
assertEquals("secondArray[0]", secondArray[0], PropertyUtils.getProperty(bean, "string2dArray[1][0]"));
assertEquals("secondArray[1]", secondArray[1], PropertyUtils.getProperty(bean, "string2dArray[1][1]"));
assertEquals("secondArray[2]", secondArray[2], PropertyUtils.getProperty(bean, "string2dArray[1][2]"));
assertEquals("secondArray[3]", secondArray[3], PropertyUtils.getProperty(bean, "string2dArray[1][3]"));
} catch (final Throwable t) {
fail("Threw " + t + "");
}
}
/**
* Test getting an indexed value out of List of Lists
*/
public void testGetIndexedList() {
final String[] firstArray = { "FIRST-1", "FIRST-2", "FIRST-3" };
final String[] secondArray = { "SECOND-1", "SECOND-2", "SECOND-3", "SECOND-4" };
final List<Object> mainList = new ArrayList<>();
mainList.add(Arrays.asList(firstArray));
mainList.add(Arrays.asList(secondArray));
final TestBean bean = new TestBean(mainList);
try {
assertEquals("firstArray[0]", firstArray[0], PropertyUtils.getProperty(bean, "listIndexed[0][0]"));
assertEquals("firstArray[1]", firstArray[1], PropertyUtils.getProperty(bean, "listIndexed[0][1]"));
assertEquals("firstArray[2]", firstArray[2], PropertyUtils.getProperty(bean, "listIndexed[0][2]"));
assertEquals("secondArray[0]", secondArray[0], PropertyUtils.getProperty(bean, "listIndexed[1][0]"));
assertEquals("secondArray[1]", secondArray[1], PropertyUtils.getProperty(bean, "listIndexed[1][1]"));
assertEquals("secondArray[2]", secondArray[2], PropertyUtils.getProperty(bean, "listIndexed[1][2]"));
assertEquals("secondArray[3]", secondArray[3], PropertyUtils.getProperty(bean, "listIndexed[1][3]"));
} catch (final Throwable t) {
fail("Threw " + t + "");
}
}
/**
* Test getting a value out of a mapped Map
*/
public void testGetIndexedMap() {
final Map<String, Object> firstMap = new HashMap<>();
firstMap.put("FIRST-KEY-1", "FIRST-VALUE-1");
firstMap.put("FIRST-KEY-2", "FIRST-VALUE-2");
final Map<String, Object> secondMap = new HashMap<>();
secondMap.put("SECOND-KEY-1", "SECOND-VALUE-1");
secondMap.put("SECOND-KEY-2", "SECOND-VALUE-2");
final List<Object> mainList = new ArrayList<>();
mainList.add(firstMap);
mainList.add(secondMap);
final TestBean bean = new TestBean(mainList);
try {
assertEquals("listIndexed[0](FIRST-KEY-1)", "FIRST-VALUE-1", PropertyUtils.getProperty(bean, "listIndexed[0](FIRST-KEY-1)"));
assertEquals("listIndexed[0](FIRST-KEY-2)", "FIRST-VALUE-2", PropertyUtils.getProperty(bean, "listIndexed[0](FIRST-KEY-2)"));
assertEquals("listIndexed[1](SECOND-KEY-1)", "SECOND-VALUE-1", PropertyUtils.getProperty(bean, "listIndexed[1](SECOND-KEY-1)"));
assertEquals("listIndexed[1](SECOND-KEY-2)", "SECOND-VALUE-2", PropertyUtils.getProperty(bean, "listIndexed[1](SECOND-KEY-2)"));
} catch (final Throwable t) {
fail("Threw " + t + "");
}
}
/**
* Positive and negative tests on getIndexedProperty valid arguments.
*/
public void testGetIndexedValues() {
Object value = null;
// Use explicit key argument
for (int i = 0; i < 5; i++) {
try {
value = PropertyUtils.getIndexedProperty(bean, "dupProperty", i);
assertNotNull("dupProperty returned value " + i, value);
assertTrue("dupProperty returned String " + i, value instanceof String);
assertEquals("dupProperty returned correct " + i, "Dup " + i, (String) value);
} catch (final Throwable t) {
fail("dupProperty " + i + " threw " + t);
}
try {
value = PropertyUtils.getIndexedProperty(bean, "intArray", i);
assertNotNull("intArray returned value " + i, value);
assertTrue("intArray returned Integer " + i, value instanceof Integer);
assertEquals("intArray returned correct " + i, i * 10, ((Integer) value).intValue());
} catch (final Throwable t) {
fail("intArray " + i + " threw " + t);
}
try {
value = PropertyUtils.getIndexedProperty(bean, "intIndexed", i);
assertNotNull("intIndexed returned value " + i, value);
assertTrue("intIndexed returned Integer " + i, value instanceof Integer);
assertEquals("intIndexed returned correct " + i, i * 10, ((Integer) value).intValue());
} catch (final Throwable t) {
fail("intIndexed " + i + " threw " + t);
}
try {
value = PropertyUtils.getIndexedProperty(bean, "listIndexed", i);
assertNotNull("listIndexed returned value " + i, value);
assertTrue("list returned String " + i, value instanceof String);
assertEquals("listIndexed returned correct " + i, "String " + i, (String) value);
} catch (final Throwable t) {
fail("listIndexed " + i + " threw " + t);
}
try {
value = PropertyUtils.getIndexedProperty(bean, "stringArray", i);
assertNotNull("stringArray returned value " + i, value);
assertTrue("stringArray returned String " + i, value instanceof String);
assertEquals("stringArray returned correct " + i, "String " + i, (String) value);
} catch (final Throwable t) {
fail("stringArray " + i + " threw " + t);
}
try {
value = PropertyUtils.getIndexedProperty(bean, "stringIndexed", i);
assertNotNull("stringIndexed returned value " + i, value);
assertTrue("stringIndexed returned String " + i, value instanceof String);
assertEquals("stringIndexed returned correct " + i, "String " + i, (String) value);
} catch (final Throwable t) {
fail("stringIndexed " + i + " threw " + t);
}
}
// Use key expression
for (int i = 0; i < 5; i++) {
try {
value = PropertyUtils.getIndexedProperty(bean, "dupProperty[" + i + "]");
assertNotNull("dupProperty returned value " + i, value);
assertTrue("dupProperty returned String " + i, value instanceof String);
assertEquals("dupProperty returned correct " + i, "Dup " + i, (String) value);
} catch (final Throwable t) {
fail("dupProperty " + i + " threw " + t);
}
try {
value = PropertyUtils.getIndexedProperty(bean, "intArray[" + i + "]");
assertNotNull("intArray returned value " + i, value);
assertTrue("intArray returned Integer " + i, value instanceof Integer);
assertEquals("intArray returned correct " + i, i * 10, ((Integer) value).intValue());
} catch (final Throwable t) {
fail("intArray " + i + " threw " + t);
}
try {
value = PropertyUtils.getIndexedProperty(bean, "intIndexed[" + i + "]");
assertNotNull("intIndexed returned value " + i, value);
assertTrue("intIndexed returned Integer " + i, value instanceof Integer);
assertEquals("intIndexed returned correct " + i, i * 10, ((Integer) value).intValue());
} catch (final Throwable t) {
fail("intIndexed " + i + " threw " + t);
}
try {
value = PropertyUtils.getIndexedProperty(bean, "listIndexed[" + i + "]");
assertNotNull("listIndexed returned value " + i, value);
assertTrue("listIndexed returned String " + i, value instanceof String);
assertEquals("listIndexed returned correct " + i, "String " + i, (String) value);
} catch (final Throwable t) {
fail("listIndexed " + i + " threw " + t);
}
try {
value = PropertyUtils.getIndexedProperty(bean, "stringArray[" + i + "]");
assertNotNull("stringArray returned value " + i, value);
assertTrue("stringArray returned String " + i, value instanceof String);
assertEquals("stringArray returned correct " + i, "String " + i, (String) value);
} catch (final Throwable t) {
fail("stringArray " + i + " threw " + t);
}
try {
value = PropertyUtils.getIndexedProperty(bean, "stringIndexed[" + i + "]");
assertNotNull("stringIndexed returned value " + i, value);
assertTrue("stringIndexed returned String " + i, value instanceof String);
assertEquals("stringIndexed returned correct " + i, "String " + i, (String) value);
} catch (final Throwable t) {
fail("stringIndexed " + i + " threw " + t);
}
}
// Index out of bounds tests
try {
value = PropertyUtils.getIndexedProperty(bean, "dupProperty", -1);
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
value = PropertyUtils.getIndexedProperty(bean, "dupProperty", 5);
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
value = PropertyUtils.getIndexedProperty(bean, "intArray", -1);
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
value = PropertyUtils.getIndexedProperty(bean, "intArray", 5);
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
value = PropertyUtils.getIndexedProperty(bean, "intIndexed", -1);
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
value = PropertyUtils.getIndexedProperty(bean, "intIndexed", 5);
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
value = PropertyUtils.getIndexedProperty(bean, "listIndexed", -1);
fail("Should have thrown IndexOutOfBoundsException");
} catch (final IndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of IndexOutOfBoundsException");
}
try {
value = PropertyUtils.getIndexedProperty(bean, "listIndexed", 5);
fail("Should have thrown IndexOutOfBoundsException");
} catch (final IndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of IndexOutOfBoundsException");
}
try {
value = PropertyUtils.getIndexedProperty(bean, "stringArray", -1);
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
value = PropertyUtils.getIndexedProperty(bean, "stringArray", 5);
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
value = PropertyUtils.getIndexedProperty(bean, "stringIndexed", -1);
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
value = PropertyUtils.getIndexedProperty(bean, "stringIndexed", 5);
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
}
/**
* Corner cases on getMappedProperty invalid arguments.
*/
public void testGetMappedArguments() {
// Use explicit key argument
try {
PropertyUtils.getMappedProperty(null, "mappedProperty", "First Key");
fail("Should throw IllegalArgumentException 1");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 1");
}
try {
PropertyUtils.getMappedProperty(bean, null, "First Key");
fail("Should throw IllegalArgumentException 2");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 2");
}
try {
PropertyUtils.getMappedProperty(bean, "mappedProperty", null);
fail("Should throw IllegalArgumentException 3");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 3");
}
// Use key expression
try {
PropertyUtils.getMappedProperty(null, "mappedProperty(First Key)");
fail("Should throw IllegalArgumentException 4");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 4");
}
try {
PropertyUtils.getMappedProperty(bean, "(Second Key)");
fail("Should throw IllegalArgumentException 5");
} catch (final NoSuchMethodException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of NoSuchMethodException 5");
}
try {
PropertyUtils.getMappedProperty(bean, "mappedProperty");
fail("Should throw IllegalArgumentException 6");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 6");
}
}
/**
* Test getting an indexed value out of a mapped array
*/
public void testGetMappedArray() {
final TestBean bean = new TestBean();
final String[] array = { "abc", "def", "ghi" };
bean.getMapProperty().put("mappedArray", array);
try {
assertEquals("abc", PropertyUtils.getProperty(bean, "mapProperty(mappedArray)[0]"));
assertEquals("def", PropertyUtils.getProperty(bean, "mapProperty(mappedArray)[1]"));
assertEquals("ghi", PropertyUtils.getProperty(bean, "mapProperty(mappedArray)[2]"));
} catch (final Throwable t) {
fail("Threw " + t + "");
}
}
/**
* Test getting an indexed value out of a mapped List
*/
public void testGetMappedList() {
final TestBean bean = new TestBean();
final List<Object> list = new ArrayList<>();
list.add("klm");
list.add("nop");
list.add("qrs");
bean.getMapProperty().put("mappedList", list);
try {
assertEquals("klm", PropertyUtils.getProperty(bean, "mapProperty(mappedList)[0]"));
assertEquals("nop", PropertyUtils.getProperty(bean, "mapProperty(mappedList)[1]"));
assertEquals("qrs", PropertyUtils.getProperty(bean, "mapProperty(mappedList)[2]"));
} catch (final Throwable t) {
fail("Threw " + t + "");
}
}
/**
* Test getting a value out of a mapped Map
*/
public void testGetMappedMap() {
final TestBean bean = new TestBean();
final Map<String, Object> map = new HashMap<>();
map.put("sub-key-1", "sub-value-1");
map.put("sub-key-2", "sub-value-2");
map.put("sub-key-3", "sub-value-3");
bean.getMapProperty().put("mappedMap", map);
try {
assertEquals("sub-value-1", PropertyUtils.getProperty(bean, "mapProperty(mappedMap)(sub-key-1)"));
assertEquals("sub-value-2", PropertyUtils.getProperty(bean, "mapProperty(mappedMap)(sub-key-2)"));
assertEquals("sub-value-3", PropertyUtils.getProperty(bean, "mapProperty(mappedMap)(sub-key-3)"));
} catch (final Throwable t) {
fail("Threw " + t + "");
}
}
/**
* Test getting mapped values with periods in the key.
*/
public void testGetMappedPeriods() {
bean.setMappedProperty("key.with.a.dot", "Special Value");
assertEquals("Can retrieve directly", "Special Value", bean.getMappedProperty("key.with.a.dot"));
try {
assertEquals("Can retrieve via getMappedProperty", "Special Value", PropertyUtils.getMappedProperty(bean, "mappedProperty", "key.with.a.dot"));
} catch (final Exception e) {
fail("Thew exception: " + e);
}
try {
assertEquals("Can retrieve via getNestedProperty", "Special Value", PropertyUtils.getNestedProperty(bean, "mappedProperty(key.with.a.dot)"));
} catch (final Exception e) {
fail("Thew exception: " + e);
}
bean.setMappedObjects("nested.property", new TestBean());
assertNotNull("Can retrieve directly", bean.getMappedObjects("nested.property"));
try {
assertEquals("Can retrieve nested", "This is a string", PropertyUtils.getNestedProperty(bean, "mappedObjects(nested.property).stringProperty"));
} catch (final Exception e) {
fail("Thew exception: " + e);
}
try {
assertEquals("Can't retrieved nested with mapped property", "Mapped Value",
PropertyUtils.getNestedProperty(bean, "mappedNested.value(Mapped Key)"));
} catch (final Exception e) {
fail("Thew exception: " + e);
}
}
/**
* Test getting mapped values with slashes in the key. This is different from periods because slashes are not syntactically significant.
*/
public void testGetMappedSlashes() {
bean.setMappedProperty("key/with/a/slash", "Special Value");
assertEquals("Can retrieve directly", "Special Value", bean.getMappedProperty("key/with/a/slash"));
try {
assertEquals("Can retrieve via getMappedProperty", "Special Value", PropertyUtils.getMappedProperty(bean, "mappedProperty", "key/with/a/slash"));
} catch (final Exception e) {
fail("Thew exception: " + e);
}
try {
assertEquals("Can retrieve via getNestedProperty", "Special Value", PropertyUtils.getNestedProperty(bean, "mappedProperty(key/with/a/slash)"));
} catch (final Exception e) {
fail("Thew exception: " + e);
}
bean.setMappedObjects("nested/property", new TestBean());
assertNotNull("Can retrieve directly", bean.getMappedObjects("nested/property"));
try {
assertEquals("Can retrieve nested", "This is a string", PropertyUtils.getNestedProperty(bean, "mappedObjects(nested/property).stringProperty"));
} catch (final Exception e) {
fail("Thew exception: " + e);
}
}
/**
* Positive and negative tests on getMappedProperty valid arguments.
*/
public void testGetMappedValues() {
Object value = null;
// Use explicit key argument
try {
value = PropertyUtils.getMappedProperty(bean, "mappedProperty", "First Key");
assertEquals("Can find first value", "First Value", value);
} catch (final Throwable t) {
fail("Finding first value threw " + t);
}
try {
value = PropertyUtils.getMappedProperty(bean, "mappedProperty", "Second Key");
assertEquals("Can find second value", "Second Value", value);
} catch (final Throwable t) {
fail("Finding second value threw " + t);
}
try {
value = PropertyUtils.getMappedProperty(bean, "mappedProperty", "Third Key");
assertNull("Can not find third value", value);
} catch (final Throwable t) {
fail("Finding third value threw " + t);
}
// Use key expression with parentheses
try {
value = PropertyUtils.getMappedProperty(bean, "mappedProperty(First Key)");
assertEquals("Can find first value", "First Value", value);
} catch (final Throwable t) {
fail("Finding first value threw " + t);
}
try {
value = PropertyUtils.getMappedProperty(bean, "mappedProperty(Second Key)");
assertEquals("Can find second value", "Second Value", value);
} catch (final Throwable t) {
fail("Finding second value threw " + t);
}
try {
value = PropertyUtils.getMappedProperty(bean, "mappedProperty(Third Key)");
assertNull("Can not find third value", value);
} catch (final Throwable t) {
fail("Finding third value threw " + t);
}
// Use key expression with dotted syntax
try {
value = PropertyUtils.getNestedProperty(bean, "mapProperty.First Key");
assertEquals("Can find first value", "First Value", value);
} catch (final Throwable t) {
fail("Finding first value threw " + t);
}
try {
value = PropertyUtils.getNestedProperty(bean, "mapProperty.Second Key");
assertEquals("Can find second value", "Second Value", value);
} catch (final Throwable t) {
fail("Finding second value threw " + t);
}
try {
value = PropertyUtils.getNestedProperty(bean, "mapProperty.Third Key");
assertNull("Can not find third value", value);
} catch (final Throwable t) {
fail("Finding third value threw " + t);
}
}
/**
* Corner cases on getNestedProperty invalid arguments.
*/
public void testGetNestedArguments() {
try {
PropertyUtils.getNestedProperty(null, "stringProperty");
fail("Should throw IllegalArgumentException 1");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 1");
}
try {
PropertyUtils.getNestedProperty(bean, null);
fail("Should throw IllegalArgumentException 2");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 2");
}
}
/**
* Test getNestedProperty on a boolean property.
*/
public void testGetNestedBoolean() {
try {
final Object value = PropertyUtils.getNestedProperty(bean, "nested.booleanProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof Boolean);
assertTrue("Got correct value", ((Boolean) value).booleanValue() == bean.getNested().getBooleanProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test getNestedProperty on a double property.
*/
public void testGetNestedDouble() {
try {
final Object value = PropertyUtils.getNestedProperty(bean, "nested.doubleProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof Double);
assertEquals("Got correct value", ((Double) value).doubleValue(), bean.getNested().getDoubleProperty(), 0.005);
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test getNestedProperty on a float property.
*/
public void testGetNestedFloat() {
try {
final Object value = PropertyUtils.getNestedProperty(bean, "nested.floatProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof Float);
assertEquals("Got correct value", ((Float) value).floatValue(), bean.getNested().getFloatProperty(), (float) 0.005);
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test getNestedProperty on an int property.
*/
public void testGetNestedInt() {
try {
final Object value = PropertyUtils.getNestedProperty(bean, "nested.intProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof Integer);
assertEquals("Got correct value", ((Integer) value).intValue(), bean.getNested().getIntProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test getNestedProperty on a long property.
*/
public void testGetNestedLong() {
try {
final Object value = PropertyUtils.getNestedProperty(bean, "nested.longProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof Long);
assertEquals("Got correct value", ((Long) value).longValue(), bean.getNested().getLongProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test getNestedProperty on a read-only String property.
*/
public void testGetNestedReadOnly() {
try {
final Object value = PropertyUtils.getNestedProperty(bean, "nested.readOnlyProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof String);
assertEquals("Got correct value", (String) value, bean.getReadOnlyProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test getNestedProperty on a short property.
*/
public void testGetNestedShort() {
try {
final Object value = PropertyUtils.getNestedProperty(bean, "nested.shortProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof Short);
assertEquals("Got correct value", ((Short) value).shortValue(), bean.getNested().getShortProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test getNestedProperty on a String property.
*/
public void testGetNestedString() {
try {
final Object value = PropertyUtils.getNestedProperty(bean, "nested.stringProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof String);
assertEquals("Got correct value", (String) value, bean.getNested().getStringProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Negative test getNestedProperty on an unknown property.
*/
public void testGetNestedUnknown() {
try {
PropertyUtils.getNestedProperty(bean, "nested.unknown");
fail("Should have thrown NoSuchMethodException");
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
// Correct result for this test
}
}
/**
* Test getNestedProperty on a write-only String property.
*/
public void testGetNestedWriteOnly() {
try {
PropertyUtils.getNestedProperty(bean, "writeOnlyProperty");
fail("Should have thrown NoSuchMethodException");
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
// Correct result for this test
}
}
/**
* Test getPropertyType() on all kinds of properties.
*/
public void testGetPropertyType() {
Class<?> clazz = null;
final int[] intArray = {};
final String[] stringArray = {};
try {
// Scalar and Indexed Properties
clazz = PropertyUtils.getPropertyType(bean, "booleanProperty");
assertEquals("booleanProperty type", Boolean.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "booleanSecond");
assertEquals("booleanSecond type", Boolean.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "doubleProperty");
assertEquals("doubleProperty type", Double.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "dupProperty");
assertEquals("dupProperty type", String.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "floatProperty");
assertEquals("floatProperty type", Float.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "intArray");
assertEquals("intArray type", intArray.getClass(), clazz);
clazz = PropertyUtils.getPropertyType(bean, "intIndexed");
assertEquals("intIndexed type", Integer.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "intProperty");
assertEquals("intProperty type", Integer.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "listIndexed");
assertEquals("listIndexed type", List.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "longProperty");
assertEquals("longProperty type", Long.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "mappedProperty");
assertEquals("mappedProperty type", String.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "mappedIntProperty");
assertEquals("mappedIntProperty type", Integer.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "readOnlyProperty");
assertEquals("readOnlyProperty type", String.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "shortProperty");
assertEquals("shortProperty type", Short.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "stringArray");
assertEquals("stringArray type", stringArray.getClass(), clazz);
clazz = PropertyUtils.getPropertyType(bean, "stringIndexed");
assertEquals("stringIndexed type", String.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "stringProperty");
assertEquals("stringProperty type", String.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "writeOnlyProperty");
assertEquals("writeOnlyProperty type", String.class, clazz);
// Nested Properties
clazz = PropertyUtils.getPropertyType(bean, "nested.booleanProperty");
assertEquals("booleanProperty type", Boolean.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.booleanSecond");
assertEquals("booleanSecond type", Boolean.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.doubleProperty");
assertEquals("doubleProperty type", Double.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.dupProperty");
assertEquals("dupProperty type", String.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.floatProperty");
assertEquals("floatProperty type", Float.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.intArray");
assertEquals("intArray type", intArray.getClass(), clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.intIndexed");
assertEquals("intIndexed type", Integer.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.intProperty");
assertEquals("intProperty type", Integer.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.listIndexed");
assertEquals("listIndexed type", List.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.longProperty");
assertEquals("longProperty type", Long.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.mappedProperty");
assertEquals("mappedProperty type", String.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.mappedIntProperty");
assertEquals("mappedIntProperty type", Integer.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.readOnlyProperty");
assertEquals("readOnlyProperty type", String.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.shortProperty");
assertEquals("shortProperty type", Short.TYPE, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.stringArray");
assertEquals("stringArray type", stringArray.getClass(), clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.stringIndexed");
assertEquals("stringIndexed type", String.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.stringProperty");
assertEquals("stringProperty type", String.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nested.writeOnlyProperty");
assertEquals("writeOnlyProperty type", String.class, clazz);
// Nested DynaBean
clazz = PropertyUtils.getPropertyType(bean, "nestedDynaBean");
assertEquals("nestedDynaBean type", DynaBean.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nestedDynaBean.stringProperty");
assertEquals("nestedDynaBean.stringProperty type", String.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nestedDynaBean.nestedBean");
assertEquals("nestedDynaBean.nestedBean type", TestBean.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nestedDynaBean.nestedBean.nestedDynaBean");
assertEquals("nestedDynaBean.nestedBean.nestedDynaBean type", DynaBean.class, clazz);
clazz = PropertyUtils.getPropertyType(bean, "nestedDynaBean.nestedBean.nestedDynaBean.stringProperty");
assertEquals("nestedDynaBean.nestedBean.nestedDynaBean.stringPropert type", String.class, clazz);
// test Null
clazz = PropertyUtils.getPropertyType(bean, "nestedDynaBean.nullDynaBean");
assertEquals("nestedDynaBean.nullDynaBean type", DynaBean.class, clazz);
try {
clazz = PropertyUtils.getPropertyType(bean, "nestedDynaBean.nullDynaBean.foo");
fail("Expected NestedNullException for nestedDynaBean.nullDynaBean.foo");
} catch (final NestedNullException e) {
// expected
}
} catch (final Exception e) {
fail("Exception: " + e.getMessage());
}
}
/**
* Test accessing a public sub-bean of a package scope bean
*/
public void testGetPublicSubBean_of_PackageBean() {
final PublicSubBean bean = new PublicSubBean();
bean.setFoo("foo-start");
bean.setBar("bar-start");
Object result = null;
// Get Foo
try {
result = PropertyUtils.getProperty(bean, "foo");
} catch (final Throwable t) {
fail("getProperty(foo) threw " + t);
}
assertEquals("foo property", "foo-start", result);
// Get Bar
try {
result = PropertyUtils.getProperty(bean, "bar");
} catch (final Throwable t) {
fail("getProperty(bar) threw " + t);
}
assertEquals("bar property", "bar-start", result);
}
/**
* Base for testGetReadMethod() series of tests.
*
* @param bean Bean for which to retrieve read methods.
* @param properties Property names to search for
* @param className Class name where this method should be defined
*/
protected void testGetReadMethod(final Object bean, final String[] properties, final String className) {
final PropertyDescriptor[] pd = PropertyUtils.getPropertyDescriptors(bean);
for (final String propertie : properties) {
// Identify the property descriptor for this property
if (propertie.equals("intIndexed")) {
continue;
}
if (propertie.equals("stringIndexed")) {
continue;
}
if (propertie.equals("writeOnlyProperty")) {
continue;
}
int n = -1;
for (int j = 0; j < pd.length; j++) {
if (propertie.equals(pd[j].getName())) {
n = j;
break;
}
}
assertTrue("PropertyDescriptor for " + propertie, n >= 0);
// Locate an accessible property reader method for it
final Method reader = PropertyUtils.getReadMethod(pd[n]);
assertNotNull("Reader for " + propertie, reader);
final Class<?> clazz = reader.getDeclaringClass();
assertNotNull("Declaring class for " + propertie, clazz);
assertEquals("Correct declaring class for " + propertie, clazz.getName(), className);
// Actually call the reader method we received
try {
reader.invoke(bean, (Object[]) new Class<?>[0]);
} catch (final Throwable t) {
fail("Call for " + propertie + ": " + t);
}
}
}
/**
* Test getting accessible property reader methods for a specified list of properties of our standard test bean.
*/
public void testGetReadMethodBasic() {
testGetReadMethod(bean, properties, TEST_BEAN_CLASS);
}
/**
* Test getting accessible property reader methods for a specified list of properties of a package private subclass of our standard test bean.
*/
public void testGetReadMethodPackageSubclass() {
testGetReadMethod(beanPackageSubclass, properties, TEST_BEAN_CLASS);
}
/**
* Test getting accessible property reader methods for a specified list of properties that are declared either directly or via implemented interfaces.
*/
public void testGetReadMethodPublicInterface() {
// Properties "bar" and "baz" are visible via implemented interfaces
// (one direct and one indirect)
testGetReadMethod(beanPrivate, new String[] { "bar" }, PRIVATE_DIRECT_CLASS);
testGetReadMethod(beanPrivate, new String[] { "baz" }, PRIVATE_INDIRECT_CLASS);
// Properties "bar" and "baz" are visible via implemented interfaces
// (one direct and one indirect). The interface is implemented in
// a superclass
testGetReadMethod(beanPrivateSubclass, new String[] { "bar" }, PRIVATE_DIRECT_CLASS);
testGetReadMethod(beanPrivateSubclass, new String[] { "baz" }, PRIVATE_INDIRECT_CLASS);
// Property "foo" is not accessible because the underlying
// class has package scope
final PropertyDescriptor[] pd = PropertyUtils.getPropertyDescriptors(beanPrivate);
int n = -1;
for (int i = 0; i < pd.length; i++) {
if ("foo".equals(pd[i].getName())) {
n = i;
break;
}
}
assertTrue("Found foo descriptor", n >= 0);
final Method reader = pd[n].getReadMethod();
assertNotNull("Found foo read method", reader);
try {
reader.invoke(beanPrivate, (Object[]) new Class<?>[0]);
fail("Foo reader did throw IllegalAccessException");
} catch (final IllegalAccessException e) {
// Expected result for this test
} catch (final Throwable t) {
fail("Invoke foo reader: " + t);
}
}
/**
* Test getting accessible property reader methods for a specified list of properties of a public subclass of our standard test bean.
*/
public void testGetReadMethodPublicSubclass() {
testGetReadMethod(beanPublicSubclass, properties, TEST_BEAN_CLASS);
}
/** Text case for setting properties on inner classes */
public void testGetSetInnerBean() throws Exception {
final BeanWithInnerBean bean = new BeanWithInnerBean();
PropertyUtils.setProperty(bean, "innerBean.fish(loiterTimer)", "5");
String out = (String) PropertyUtils.getProperty(bean.getInnerBean(), "fish(loiterTimer)");
assertEquals("(1) Inner class property set/get property failed.", "5", out);
out = (String) PropertyUtils.getProperty(bean, "innerBean.fish(loiterTimer)");
assertEquals("(2) Inner class property set/get property failed.", "5", out);
}
/** Text case for setting properties on parent */
public void testGetSetParentBean() throws Exception {
final SonOfAlphaBean bean = new SonOfAlphaBean("Roger");
final String out = (String) PropertyUtils.getProperty(bean, "name");
assertEquals("(1) Get/Set On Parent.", "Roger", out);
PropertyUtils.setProperty(bean, "name", "abcd");
assertEquals("(2) Get/Set On Parent.", "abcd", bean.getName());
}
/**
* Corner cases on getSimpleProperty invalid arguments.
*/
public void testGetSimpleArguments() {
try {
PropertyUtils.getSimpleProperty(null, "stringProperty");
fail("Should throw IllegalArgumentException 1");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 1");
}
try {
PropertyUtils.getSimpleProperty(bean, null);
fail("Should throw IllegalArgumentException 2");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 2");
}
}
/**
* Test getSimpleProperty on a boolean property.
*/
public void testGetSimpleBoolean() {
try {
final Object value = PropertyUtils.getSimpleProperty(bean, "booleanProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof Boolean);
assertTrue("Got correct value", ((Boolean) value).booleanValue() == bean.getBooleanProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test getSimpleProperty on a double property.
*/
public void testGetSimpleDouble() {
try {
final Object value = PropertyUtils.getSimpleProperty(bean, "doubleProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof Double);
assertEquals("Got correct value", ((Double) value).doubleValue(), bean.getDoubleProperty(), 0.005);
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test getSimpleProperty on a float property.
*/
public void testGetSimpleFloat() {
try {
final Object value = PropertyUtils.getSimpleProperty(bean, "floatProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof Float);
assertEquals("Got correct value", ((Float) value).floatValue(), bean.getFloatProperty(), (float) 0.005);
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Negative test getSimpleProperty on an indexed property.
*/
public void testGetSimpleIndexed() {
try {
PropertyUtils.getSimpleProperty(bean, "intIndexed[0]");
fail("Should have thrown IllegalArgumentException");
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
// Correct result for this test
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test getSimpleProperty on an int property.
*/
public void testGetSimpleInt() {
try {
final Object value = PropertyUtils.getSimpleProperty(bean, "intProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof Integer);
assertEquals("Got correct value", ((Integer) value).intValue(), bean.getIntProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test getSimpleProperty on a long property.
*/
public void testGetSimpleLong() {
try {
final Object value = PropertyUtils.getSimpleProperty(bean, "longProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof Long);
assertEquals("Got correct value", ((Long) value).longValue(), bean.getLongProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Negative test getSimpleProperty on a nested property.
*/
public void testGetSimpleNested() {
try {
PropertyUtils.getSimpleProperty(bean, "nested.stringProperty");
fail("Should have thrown IllegalArgumentException");
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
// Correct result for this test
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test getSimpleProperty on a read-only String property.
*/
public void testGetSimpleReadOnly() {
try {
final Object value = PropertyUtils.getSimpleProperty(bean, "readOnlyProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof String);
assertEquals("Got correct value", (String) value, bean.getReadOnlyProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test getSimpleProperty on a short property.
*/
public void testGetSimpleShort() {
try {
final Object value = PropertyUtils.getSimpleProperty(bean, "shortProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof Short);
assertEquals("Got correct value", ((Short) value).shortValue(), bean.getShortProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test getSimpleProperty on a String property.
*/
public void testGetSimpleString() {
try {
final Object value = PropertyUtils.getSimpleProperty(bean, "stringProperty");
assertNotNull("Got a value", value);
assertTrue("Got correct type", value instanceof String);
assertEquals("Got correct value", (String) value, bean.getStringProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Negative test getSimpleProperty on an unknown property.
*/
public void testGetSimpleUnknown() {
try {
PropertyUtils.getSimpleProperty(bean, "unknown");
fail("Should have thrown NoSuchMethodException");
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
// Correct result for this test
assertEquals("Unknown property 'unknown' on class '" + bean.getClass() + "'", e.getMessage());
}
}
/**
* Test getSimpleProperty on a write-only String property.
*/
public void testGetSimpleWriteOnly() {
try {
PropertyUtils.getSimpleProperty(bean, "writeOnlyProperty");
fail("Should have thrown NoSuchMethodException");
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
// Correct result for this test
assertEquals("Property 'writeOnlyProperty' has no getter method in class '" + bean.getClass() + "'", e.getMessage());
}
}
/**
* Base for testGetWriteMethod() series of tests.
*
* @param bean Bean for which to retrieve write methods.
* @param properties Property names to search for
* @param className Class name where this method should be defined
*/
protected void testGetWriteMethod(final Object bean, final String[] properties, final String className) {
final PropertyDescriptor[] pd = PropertyUtils.getPropertyDescriptors(bean);
for (final String property : properties) {
// Identify the property descriptor for this property
if (property.equals("intIndexed")) {
continue;
}
if (property.equals("listIndexed")) {
continue;
}
if (property.equals("nested")) {
continue; // This property is read only
}
if (property.equals("readOnlyProperty")) {
continue;
}
if (property.equals("stringIndexed")) {
continue;
}
int n = -1;
for (int j = 0; j < pd.length; j++) {
if (property.equals(pd[j].getName())) {
n = j;
break;
}
}
assertTrue("PropertyDescriptor for " + property, n >= 0);
// Locate an accessible property reader method for it
final Method writer = PropertyUtils.getWriteMethod(pd[n]);
assertNotNull("Writer for " + property, writer);
final Class<?> clazz = writer.getDeclaringClass();
assertNotNull("Declaring class for " + property, clazz);
assertEquals("Correct declaring class for " + property, clazz.getName(), className);
}
}
/**
* Test getting accessible property writer methods for a specified list of properties of our standard test bean.
*/
public void testGetWriteMethodBasic() {
testGetWriteMethod(bean, properties, TEST_BEAN_CLASS);
}
/**
* Test getting accessible property writer methods for a specified list of properties of a package private subclass of our standard test bean.
*/
public void testGetWriteMethodPackageSubclass() {
testGetWriteMethod(beanPackageSubclass, properties, TEST_BEAN_CLASS);
}
/**
* Test getting accessible property writer methods for a specified list of properties of a public subclass of our standard test bean.
*/
public void testGetWriteMethodPublicSubclass() {
testGetWriteMethod(beanPublicSubclass, properties, TEST_BEAN_CLASS);
}
/**
* Test isReadable() method.
*/
public void testIsReadable() {
String property = null;
try {
property = "stringProperty";
assertTrue("Property " + property + " isReadable expected TRUE", PropertyUtils.isReadable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isReadable Threw exception: " + t);
}
try {
property = "stringIndexed";
assertTrue("Property " + property + " isReadable expected TRUE", PropertyUtils.isReadable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isReadable Threw exception: " + t);
}
try {
property = "mappedProperty";
assertTrue("Property " + property + " isReadable expected TRUE", PropertyUtils.isReadable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isReadable Threw exception: " + t);
}
try {
property = "nestedDynaBean";
assertTrue("Property " + property + " isReadable expected TRUE", PropertyUtils.isReadable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isReadable Threw exception: " + t);
}
try {
property = "nestedDynaBean.stringProperty";
assertTrue("Property " + property + " isReadable expected TRUE", PropertyUtils.isReadable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isReadable Threw exception: " + t);
}
try {
property = "nestedDynaBean.nestedBean";
assertTrue("Property " + property + " isReadable expected TRUE", PropertyUtils.isReadable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isReadable Threw exception: " + t);
}
try {
property = "nestedDynaBean.nestedBean.nestedDynaBean";
assertTrue("Property " + property + " isReadable expected TRUE", PropertyUtils.isReadable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isReadable Threw exception: " + t);
}
try {
property = "nestedDynaBean.nestedBean.nestedDynaBean.stringProperty";
assertTrue("Property " + property + " isReadable expected TRUE", PropertyUtils.isReadable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isReadable Threw exception: " + t);
}
try {
property = "nestedDynaBean.nullDynaBean";
assertTrue("Property " + property + " isReadable expected TRUE", PropertyUtils.isReadable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isReadable Threw exception: " + t);
}
try {
property = "nestedDynaBean.nullDynaBean.foo";
assertTrue("Property " + property + " isReadable expected TRUE", PropertyUtils.isReadable(bean, property));
fail("Property " + property + " isReadable expected NestedNullException");
} catch (final NestedNullException e) {
// expected result
} catch (final Throwable t) {
fail("Property " + property + " isReadable Threw exception: " + t);
}
}
/**
* Test isWriteable() method.
*/
public void testIsWriteable() {
String property = null;
try {
property = "stringProperty";
assertTrue("Property " + property + " isWriteable expected TRUE", PropertyUtils.isWriteable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isWriteable Threw exception: " + t);
}
try {
property = "stringIndexed";
assertTrue("Property " + property + " isWriteable expected TRUE", PropertyUtils.isWriteable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isWriteable Threw exception: " + t);
}
try {
property = "mappedProperty";
assertTrue("Property " + property + " isWriteable expected TRUE", PropertyUtils.isWriteable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isWriteable Threw exception: " + t);
}
try {
property = "nestedDynaBean";
assertTrue("Property " + property + " isWriteable expected TRUE", PropertyUtils.isWriteable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isWriteable Threw exception: " + t);
}
try {
property = "nestedDynaBean.stringProperty";
assertTrue("Property " + property + " isWriteable expected TRUE", PropertyUtils.isWriteable(bean, property));
} catch (final Throwable t) {
t.printStackTrace();
fail("Property " + property + " isWriteable Threw exception: " + t);
}
try {
property = "nestedDynaBean.nestedBean";
assertTrue("Property " + property + " isWriteable expected TRUE", PropertyUtils.isWriteable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isWriteable Threw exception: " + t);
}
try {
property = "nestedDynaBean.nestedBean.nestedDynaBean";
assertTrue("Property " + property + " isWriteable expected TRUE", PropertyUtils.isWriteable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isWriteable Threw exception: " + t);
}
try {
property = "nestedDynaBean.nestedBean.nestedDynaBean.stringProperty";
assertTrue("Property " + property + " isWriteable expected TRUE", PropertyUtils.isWriteable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isWriteable Threw exception: " + t);
}
try {
property = "nestedDynaBean.nullDynaBean";
assertTrue("Property " + property + " isWriteable expected TRUE", PropertyUtils.isWriteable(bean, property));
} catch (final Throwable t) {
fail("Property " + property + " isWriteable Threw exception: " + t);
}
try {
property = "nestedDynaBean.nullDynaBean.foo";
assertTrue("Property " + property + " isWriteable expected TRUE", PropertyUtils.isWriteable(bean, property));
fail("Property " + property + " isWriteable expected NestedNullException");
} catch (final NestedNullException e) {
// expected result
} catch (final Throwable t) {
fail("Property " + property + " isWriteable Threw exception: " + t);
}
}
/**
* This tests to see that it is possible to subclass PropertyUtilsBean and change the behavior of setNestedProperty/getNestedProperty when dealing with
* objects that implement Map.
*/
public void testMapExtensionCustom() throws Exception {
final PropsFirstPropertyUtilsBean utilsBean = new PropsFirstPropertyUtilsBean();
final ExtendMapBean bean = new ExtendMapBean();
// hardly worth testing this, really :-)
bean.setUnusuallyNamedProperty("bean value");
assertEquals("Set property direct failed", "bean value", bean.getUnusuallyNamedProperty());
// setSimpleProperty should affect the simple property
utilsBean.setSimpleProperty(bean, "unusuallyNamedProperty", "new value");
assertEquals("Set property on map failed (1)", "new value", bean.getUnusuallyNamedProperty());
// setNestedProperty with setter should affect the simple property
// getNestedProperty with getter should obtain the simple property
utilsBean.setProperty(bean, "unusuallyNamedProperty", "next value");
assertEquals("Set property on map failed (2)", "next value", bean.getUnusuallyNamedProperty());
assertEquals("setNestedProperty on non-simple property failed", "next value", utilsBean.getNestedProperty(bean, "unusuallyNamedProperty"));
// setting property without setter should update the map
// getting property without setter should fetch from the map
utilsBean.setProperty(bean, "mapProperty", "value1");
assertEquals("setNestedProperty on non-simple property failed", "value1", utilsBean.getNestedProperty(bean, "mapProperty"));
final HashMap<String, Object> myMap = new HashMap<>();
myMap.put("thebean", bean);
utilsBean.getNestedProperty(myMap, "thebean.mapitem");
utilsBean.getNestedProperty(myMap, "thebean(mapitem)");
}
/**
* This tests to see that classes that implement Map always have their custom properties ignored.
* <p>
* Note that this behavior has changed several times over past releases of beanutils, breaking backwards compatibility each time. Here's hoping that the
* current 1.7.1 release is the last time this behavior changes!
*/
public void testMapExtensionDefault() throws Exception {
final ExtendMapBean bean = new ExtendMapBean();
// setting property direct should work, and not affect map
bean.setUnusuallyNamedProperty("bean value");
assertEquals("Set property direct failed", "bean value", bean.getUnusuallyNamedProperty());
assertNull("Get on unset map property failed", PropertyUtils.getNestedProperty(bean, "unusuallyNamedProperty"));
// setting simple property should call the setter method only, and not
// affect the map.
PropertyUtils.setSimpleProperty(bean, "unusuallyNamedProperty", "new value");
assertEquals("Set property on map failed (1)", "new value", bean.getUnusuallyNamedProperty());
assertNull("Get on unset map property failed", PropertyUtils.getNestedProperty(bean, "unusuallyNamedProperty"));
// setting via setNestedProperty should affect the map only, and not
// call the setter method.
PropertyUtils.setProperty(bean, "unusuallyNamedProperty", "next value");
assertEquals("setNestedProperty on map not visible to getNestedProperty", "next value",
PropertyUtils.getNestedProperty(bean, "unusuallyNamedProperty"));
assertEquals("Set nested property on map unexpected affected simple property", "new value", bean.getUnusuallyNamedProperty());
}
/**
* Test the mappedPropertyType of MappedPropertyDescriptor.
*/
public void testMappedPropertyType() throws Exception {
MappedPropertyDescriptor desc;
// Check a String property
desc = (MappedPropertyDescriptor) PropertyUtils.getPropertyDescriptor(bean, "mappedProperty");
assertEquals(String.class, desc.getMappedPropertyType());
// Check an int property
desc = (MappedPropertyDescriptor) PropertyUtils.getPropertyDescriptor(bean, "mappedIntProperty");
assertEquals(Integer.TYPE, desc.getMappedPropertyType());
}
/**
* There is an issue in setNestedProperty/getNestedProperty when the target bean is a map and the name string requests mapped or indexed operations on a
* field. These are not supported for fields of a Map, but it's an easy mistake to make and this test case ensures that an appropriate exception is thrown
* when a user does this.
* <p>
* The problem is with passing strings of form "a(b)" or "a[3]" to setNestedProperty or getNestedProperty when the target bean they are applied to
* implements Map. These strings are actually requesting "the result of calling mapped method a on the target object with a parameter of b" or "the result
* of calling indexed method a on the target object with a parameter of 3". And these requests are not valid when the target is a Map as a Map only supports
* calling get(fieldName) or put(fieldName), neither of which can be further indexed with a string or an integer.
* <p>
* However it is likely that some users will assume that "a[3]" when applied to a map will be equivalent to (map.get("a"))[3] with the appropriate
* typecasting, or for "a(b)" to be equivalent to map.get("a").get("b").
* <p>
* Here we verify that an exception is thrown if the user makes this mistake.
*/
public void testNestedPropertyKeyOrIndexOnBeanImplementingMap() throws Exception {
final HashMap<String, Object> map = new HashMap<>();
final HashMap<String, Object> submap = new HashMap<>();
final BetaBean betaBean1 = new BetaBean("test1");
final BetaBean betaBean2 = new BetaBean("test2");
// map.put("submap", submap)
PropertyUtils.setNestedProperty(map, "submap", submap);
// map.get("submap").put("beta1", betaBean1)
PropertyUtils.setNestedProperty(map, "submap.beta1", betaBean1);
assertEquals("Unexpected keys in map", "submap", keysToString(map));
assertEquals("Unexpected keys in submap", "beta1", keysToString(submap));
try {
// One would expect that the command below would be equivalent to
// Map m = (Map) map.get("submap");
// m.put("beta2", betaBean2)
// However this isn't how javabeans property methods work. A map
// only effectively has "simple" properties, even when the
// returned object is a Map or Array.
PropertyUtils.setNestedProperty(map, "submap(beta2)", betaBean2);
// What, no exception? In that case, setNestedProperties has
// probably just tried to do
// map.set("submap(beta2)", betaBean2)
// which is almost certainly not what the used expected. This is
// what beanutils 1.5.0 to 1.7.1 did....
fail("Exception not thrown for invalid setNestedProperty syntax");
} catch (final IllegalArgumentException ex) {
// ok, getting an exception was expected. As it is of a generic
// type, let's check the message string to make sure it really
// was caused by the issue we expected.
final int index = ex.getMessage().indexOf("Indexed or mapped properties are not supported");
assertTrue("Unexpected exception message", index >= 0);
}
try {
// One would expect that "submap[3]" would be equivalent to
// Object[] objects = (Object[]) map.get("submap");
// return objects[3];
// However this isn't how javabeans property methods work. A map
// only effectively has "simple" properties, even when the
// returned object is a Map or Array.
PropertyUtils.getNestedProperty(map, "submap[3]");
// What, no exception? In that case, getNestedProperties has
// probably just tried to do
// map.get("submap[3]")
// which is almost certainly not what the used expected. This is
// what beanutils 1.5.0 to 1.7.1 did....
fail("Exception not thrown for invalid setNestedProperty syntax");
} catch (final IllegalArgumentException ex) {
// ok, getting an exception was expected. As it is of a generic
// type, let's check the message string to make sure it really
// was caused by the issue we expected.
final int index = ex.getMessage().indexOf("Indexed or mapped properties are not supported");
assertTrue("Unexpected exception message", index >= 0);
}
}
public void testNestedWithIndex() throws Exception {
final NestedTestBean nestedBean = new NestedTestBean("base");
nestedBean.init();
nestedBean.getSimpleBeanProperty().init();
NestedTestBean
// test first calling properties on indexed beans
value = (NestedTestBean) PropertyUtils.getProperty(nestedBean, "indexedProperty[0]");
assertEquals("Cannot get simple index(1)", "Bean@0", value.getName());
assertEquals("Bug in NestedTestBean", "NOT SET", value.getTestString());
value = (NestedTestBean) PropertyUtils.getProperty(nestedBean, "indexedProperty[1]");
assertEquals("Cannot get simple index(1)", "Bean@1", value.getName());
assertEquals("Bug in NestedTestBean", "NOT SET", value.getTestString());
String prop = (String) PropertyUtils.getProperty(nestedBean, "indexedProperty[0].testString");
assertEquals("Get property on indexes failed (1)", "NOT SET", prop);
prop = (String) PropertyUtils.getProperty(nestedBean, "indexedProperty[1].testString");
assertEquals("Get property on indexes failed (2)", "NOT SET", prop);
PropertyUtils.setProperty(nestedBean, "indexedProperty[0].testString", "Test#1");
assertEquals("Cannot set property on indexed bean (1)", "Test#1", nestedBean.getIndexedProperty(0).getTestString());
PropertyUtils.setProperty(nestedBean, "indexedProperty[1].testString", "Test#2");
assertEquals("Cannot set property on indexed bean (2)", "Test#2", nestedBean.getIndexedProperty(1).getTestString());
// test first calling indexed properties on a simple property
value = (NestedTestBean) PropertyUtils.getProperty(nestedBean, "simpleBeanProperty");
assertEquals("Cannot get simple bean", "Simple Property Bean", value.getName());
assertEquals("Bug in NestedTestBean", "NOT SET", value.getTestString());
value = (NestedTestBean) PropertyUtils.getProperty(nestedBean, "simpleBeanProperty.indexedProperty[3]");
assertEquals("Cannot get index property on property", "Bean@3", value.getName());
assertEquals("Bug in NestedTestBean", "NOT SET", value.getTestString());
PropertyUtils.setProperty(nestedBean, "simpleBeanProperty.indexedProperty[3].testString", "Test#3");
assertEquals("Cannot set property on indexed property on property", "Test#3", nestedBean.getSimpleBeanProperty().getIndexedProperty(3).getTestString());
}
/**
* Tests whether a BeanIntrospector can be removed.
*/
public void testRemoveBeanIntrospector() {
assertTrue("Wrong result", PropertyUtils.removeBeanIntrospector(DefaultBeanIntrospector.INSTANCE));
final PropertyDescriptor[] desc = PropertyUtils.getPropertyDescriptors(AlphaBean.class);
assertEquals("Got descriptors", 0, desc.length);
PropertyUtils.addBeanIntrospector(DefaultBeanIntrospector.INSTANCE);
}
/**
* Tests whether a reset of the registered BeanIntrospectors can be performed.
*/
public void testResetBeanIntrospectors() {
assertTrue("Wrong result", PropertyUtils.removeBeanIntrospector(DefaultBeanIntrospector.INSTANCE));
PropertyUtils.resetBeanIntrospectors();
final PropertyDescriptor[] desc = PropertyUtils.getPropertyDescriptors(AlphaBean.class);
assertTrue("Got no descriptors", desc.length > 0);
}
/**
* Corner cases on setIndexedProperty invalid arguments.
*/
public void testSetIndexedArguments() {
// Use explicit index argument
try {
PropertyUtils.setIndexedProperty(null, "intArray", 0, Integer.valueOf(1));
fail("Should throw IllegalArgumentException 1");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 1");
}
try {
PropertyUtils.setIndexedProperty(bean, null, 0, Integer.valueOf(1));
fail("Should throw IllegalArgumentException 2");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 2");
}
// Use index expression
try {
PropertyUtils.setIndexedProperty(null, "intArray[0]", Integer.valueOf(1));
fail("Should throw IllegalArgumentException 3");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 3");
}
try {
PropertyUtils.setIndexedProperty(bean, "[0]", Integer.valueOf(1));
fail("Should throw NoSuchMethodException 4");
} catch (final NoSuchMethodException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of NoSuchMethodException 4");
}
try {
PropertyUtils.setIndexedProperty(bean, "intArray", Integer.valueOf(1));
fail("Should throw IllegalArgumentException 5");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 5");
}
// Use explicit index argument
try {
PropertyUtils.setIndexedProperty(null, "intIndexed", 0, Integer.valueOf(1));
fail("Should throw IllegalArgumentException 1");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 1");
}
try {
PropertyUtils.setIndexedProperty(bean, null, 0, Integer.valueOf(1));
fail("Should throw IllegalArgumentException 2");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 2");
}
// Use index expression
try {
PropertyUtils.setIndexedProperty(null, "intIndexed[0]", Integer.valueOf(1));
fail("Should throw IllegalArgumentException 3");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 3");
}
try {
PropertyUtils.setIndexedProperty(bean, "[0]", Integer.valueOf(1));
fail("Should throw NoSuchMethodException 4");
} catch (final NoSuchMethodException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of NoSuchMethodException 4");
}
try {
PropertyUtils.setIndexedProperty(bean, "intIndexed", Integer.valueOf(1));
fail("Should throw IllegalArgumentException 5");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 5");
}
}
/**
* Test setting an indexed value out of a multi-dimensional array
*/
public void testSetIndexedArray() {
final String[] firstArray = { "FIRST-1", "FIRST-2", "FIRST-3" };
final String[] secondArray = { "SECOND-1", "SECOND-2", "SECOND-3", "SECOND-4" };
final String[][] mainArray = { firstArray, secondArray };
final TestBean bean = new TestBean(mainArray);
assertEquals("BEFORE", "SECOND-3", bean.getString2dArray(1)[2]);
try {
PropertyUtils.setProperty(bean, "string2dArray[1][2]", "SECOND-3-UPDATED");
} catch (final Throwable t) {
fail("Threw " + t + "");
}
assertEquals("AFTER", "SECOND-3-UPDATED", bean.getString2dArray(1)[2]);
}
/**
* Test setting an indexed value out of List of Lists
*/
public void testSetIndexedList() {
final String[] firstArray = { "FIRST-1", "FIRST-2", "FIRST-3" };
final String[] secondArray = { "SECOND-1", "SECOND-2", "SECOND-3", "SECOND-4" };
final List<Object> mainList = new ArrayList<>();
mainList.add(Arrays.asList(firstArray));
mainList.add(Arrays.asList(secondArray));
final TestBean bean = new TestBean(mainList);
assertEquals("BEFORE", "SECOND-4", ((List<?>) bean.getListIndexed().get(1)).get(3));
try {
PropertyUtils.setProperty(bean, "listIndexed[1][3]", "SECOND-4-UPDATED");
} catch (final Throwable t) {
fail("Threw " + t + "");
}
assertEquals("AFTER", "SECOND-4-UPDATED", ((List<?>) bean.getListIndexed().get(1)).get(3));
}
/**
* Test setting a value out of a mapped Map
*/
public void testSetIndexedMap() {
final Map<String, Object> firstMap = new HashMap<>();
firstMap.put("FIRST-KEY-1", "FIRST-VALUE-1");
firstMap.put("FIRST-KEY-2", "FIRST-VALUE-2");
final Map<String, Object> secondMap = new HashMap<>();
secondMap.put("SECOND-KEY-1", "SECOND-VALUE-1");
secondMap.put("SECOND-KEY-2", "SECOND-VALUE-2");
final List<Object> mainList = new ArrayList<>();
mainList.add(firstMap);
mainList.add(secondMap);
final TestBean bean = new TestBean(mainList);
assertEquals("BEFORE", null, ((Map<?, ?>) bean.getListIndexed().get(0)).get("FIRST-NEW-KEY"));
assertEquals("BEFORE", "SECOND-VALUE-1", ((Map<?, ?>) bean.getListIndexed().get(1)).get("SECOND-KEY-1"));
try {
PropertyUtils.setProperty(bean, "listIndexed[0](FIRST-NEW-KEY)", "FIRST-NEW-VALUE");
PropertyUtils.setProperty(bean, "listIndexed[1](SECOND-KEY-1)", "SECOND-VALUE-1-UPDATED");
} catch (final Throwable t) {
fail("Threw " + t + "");
}
assertEquals("BEFORE", "FIRST-NEW-VALUE", ((Map<?, ?>) bean.getListIndexed().get(0)).get("FIRST-NEW-KEY"));
assertEquals("AFTER", "SECOND-VALUE-1-UPDATED", ((Map<?, ?>) bean.getListIndexed().get(1)).get("SECOND-KEY-1"));
}
/**
* Positive and negative tests on setIndexedProperty valid arguments.
*/
public void testSetIndexedValues() {
Object value = null;
// Use explicit index argument
try {
PropertyUtils.setIndexedProperty(bean, "dupProperty", 0, "New 0");
value = PropertyUtils.getIndexedProperty(bean, "dupProperty", 0);
assertNotNull("Returned new value 0", value);
assertTrue("Returned String new value 0", value instanceof String);
assertEquals("Returned correct new value 0", "New 0", (String) value);
} catch (final Throwable t) {
fail("Threw " + t);
}
try {
PropertyUtils.setIndexedProperty(bean, "intArray", 0, Integer.valueOf(1));
value = PropertyUtils.getIndexedProperty(bean, "intArray", 0);
assertNotNull("Returned new value 0", value);
assertTrue("Returned Integer new value 0", value instanceof Integer);
assertEquals("Returned correct new value 0", 1, ((Integer) value).intValue());
} catch (final Throwable t) {
fail("Threw " + t);
}
try {
PropertyUtils.setIndexedProperty(bean, "intIndexed", 1, Integer.valueOf(11));
value = PropertyUtils.getIndexedProperty(bean, "intIndexed", 1);
assertNotNull("Returned new value 1", value);
assertTrue("Returned Integer new value 1", value instanceof Integer);
assertEquals("Returned correct new value 1", 11, ((Integer) value).intValue());
} catch (final Throwable t) {
fail("Threw " + t);
}
try {
PropertyUtils.setIndexedProperty(bean, "listIndexed", 2, "New Value 2");
value = PropertyUtils.getIndexedProperty(bean, "listIndexed", 2);
assertNotNull("Returned new value 2", value);
assertTrue("Returned String new value 2", value instanceof String);
assertEquals("Returned correct new value 2", "New Value 2", (String) value);
} catch (final Throwable t) {
fail("Threw " + t);
}
try {
PropertyUtils.setIndexedProperty(bean, "stringArray", 2, "New Value 2");
value = PropertyUtils.getIndexedProperty(bean, "stringArray", 2);
assertNotNull("Returned new value 2", value);
assertTrue("Returned String new value 2", value instanceof String);
assertEquals("Returned correct new value 2", "New Value 2", (String) value);
} catch (final Throwable t) {
fail("Threw " + t);
}
try {
PropertyUtils.setIndexedProperty(bean, "stringArray", 3, "New Value 3");
value = PropertyUtils.getIndexedProperty(bean, "stringArray", 3);
assertNotNull("Returned new value 3", value);
assertTrue("Returned String new value 3", value instanceof String);
assertEquals("Returned correct new value 3", "New Value 3", (String) value);
} catch (final Throwable t) {
fail("Threw " + t);
}
// Use index expression
try {
PropertyUtils.setIndexedProperty(bean, "dupProperty[4]", "New 4");
value = PropertyUtils.getIndexedProperty(bean, "dupProperty[4]");
assertNotNull("Returned new value 4", value);
assertTrue("Returned String new value 4", value instanceof String);
assertEquals("Returned correct new value 4", "New 4", (String) value);
} catch (final Throwable t) {
fail("Threw " + t);
}
try {
PropertyUtils.setIndexedProperty(bean, "intArray[4]", Integer.valueOf(1));
value = PropertyUtils.getIndexedProperty(bean, "intArray[4]");
assertNotNull("Returned new value 4", value);
assertTrue("Returned Integer new value 4", value instanceof Integer);
assertEquals("Returned correct new value 4", 1, ((Integer) value).intValue());
} catch (final Throwable t) {
fail("Threw " + t);
}
try {
PropertyUtils.setIndexedProperty(bean, "intIndexed[3]", Integer.valueOf(11));
value = PropertyUtils.getIndexedProperty(bean, "intIndexed[3]");
assertNotNull("Returned new value 5", value);
assertTrue("Returned Integer new value 5", value instanceof Integer);
assertEquals("Returned correct new value 5", 11, ((Integer) value).intValue());
} catch (final Throwable t) {
fail("Threw " + t);
}
try {
PropertyUtils.setIndexedProperty(bean, "listIndexed[1]", "New Value 2");
value = PropertyUtils.getIndexedProperty(bean, "listIndexed[1]");
assertNotNull("Returned new value 6", value);
assertTrue("Returned String new value 6", value instanceof String);
assertEquals("Returned correct new value 6", "New Value 2", (String) value);
} catch (final Throwable t) {
fail("Threw " + t);
}
try {
PropertyUtils.setIndexedProperty(bean, "stringArray[1]", "New Value 2");
value = PropertyUtils.getIndexedProperty(bean, "stringArray[2]");
assertNotNull("Returned new value 6", value);
assertTrue("Returned String new value 6", value instanceof String);
assertEquals("Returned correct new value 6", "New Value 2", (String) value);
} catch (final Throwable t) {
fail("Threw " + t);
}
try {
PropertyUtils.setIndexedProperty(bean, "stringArray[0]", "New Value 3");
value = PropertyUtils.getIndexedProperty(bean, "stringArray[0]");
assertNotNull("Returned new value 7", value);
assertTrue("Returned String new value 7", value instanceof String);
assertEquals("Returned correct new value 7", "New Value 3", (String) value);
} catch (final Throwable t) {
fail("Threw " + t);
}
// Index out of bounds tests
try {
PropertyUtils.setIndexedProperty(bean, "dupProperty", -1, "New -1");
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
PropertyUtils.setIndexedProperty(bean, "dupProperty", 5, "New 5");
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
PropertyUtils.setIndexedProperty(bean, "intArray", -1, Integer.valueOf(0));
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
PropertyUtils.setIndexedProperty(bean, "intArray", 5, Integer.valueOf(0));
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
PropertyUtils.setIndexedProperty(bean, "intIndexed", -1, Integer.valueOf(0));
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
PropertyUtils.setIndexedProperty(bean, "intIndexed", 5, Integer.valueOf(0));
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
PropertyUtils.setIndexedProperty(bean, "listIndexed", 5, "New String");
fail("Should have thrown IndexOutOfBoundsException");
} catch (final IndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of IndexOutOfBoundsException");
}
try {
PropertyUtils.setIndexedProperty(bean, "listIndexed", -1, "New String");
fail("Should have thrown IndexOutOfBoundsException");
} catch (final IndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of IndexOutOfBoundsException");
}
try {
PropertyUtils.setIndexedProperty(bean, "stringArray", -1, "New String");
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
PropertyUtils.setIndexedProperty(bean, "stringArray", 5, "New String");
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
PropertyUtils.setIndexedProperty(bean, "stringIndexed", -1, "New String");
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
try {
PropertyUtils.setIndexedProperty(bean, "stringIndexed", 5, "New String");
fail("Should have thrown ArrayIndexOutOfBoundsException");
} catch (final ArrayIndexOutOfBoundsException t) {
// Expected results
} catch (final Throwable t) {
fail("Threw " + t + " instead of ArrayIndexOutOfBoundsException");
}
}
/**
* Corner cases on getMappedProperty invalid arguments.
*/
public void testSetMappedArguments() {
// Use explicit key argument
try {
PropertyUtils.setMappedProperty(null, "mappedProperty", "First Key", "First Value");
fail("Should throw IllegalArgumentException 1");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 1");
}
try {
PropertyUtils.setMappedProperty(bean, null, "First Key", "First Value");
fail("Should throw IllegalArgumentException 2");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 2");
}
try {
PropertyUtils.setMappedProperty(bean, "mappedProperty", null, "First Value");
fail("Should throw IllegalArgumentException 3");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 3");
}
// Use key expression
try {
PropertyUtils.setMappedProperty(null, "mappedProperty(First Key)", "First Value");
fail("Should throw IllegalArgumentException 4");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 4");
}
try {
PropertyUtils.setMappedProperty(bean, "(Second Key)", "Second Value");
fail("Should throw IllegalArgumentException 5");
} catch (final NoSuchMethodException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of NoSuchMethodException 5");
}
try {
PropertyUtils.setMappedProperty(bean, "mappedProperty", "Third Value");
fail("Should throw IllegalArgumentException 6");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 6");
}
}
/**
* Test setting an indexed value out of a mapped array
*/
public void testSetMappedArray() {
final TestBean bean = new TestBean();
final String[] array = { "abc", "def", "ghi" };
bean.getMapProperty().put("mappedArray", array);
assertEquals("BEFORE", "def", ((String[]) bean.getMapProperty().get("mappedArray"))[1]);
try {
PropertyUtils.setProperty(bean, "mapProperty(mappedArray)[1]", "DEF-UPDATED");
} catch (final Throwable t) {
fail("Threw " + t + "");
}
assertEquals("AFTER", "DEF-UPDATED", ((String[]) bean.getMapProperty().get("mappedArray"))[1]);
}
/**
* Test setting an indexed value out of a mapped List
*/
public void testSetMappedList() {
final TestBean bean = new TestBean();
final List<Object> list = new ArrayList<>();
list.add("klm");
list.add("nop");
list.add("qrs");
bean.getMapProperty().put("mappedList", list);
assertEquals("BEFORE", "klm", ((List<?>) bean.getMapProperty().get("mappedList")).get(0));
try {
PropertyUtils.setProperty(bean, "mapProperty(mappedList)[0]", "KLM-UPDATED");
} catch (final Throwable t) {
fail("Threw " + t + "");
}
assertEquals("AFTER", "KLM-UPDATED", ((List<?>) bean.getMapProperty().get("mappedList")).get(0));
}
/**
* Test setting a value out of a mapped Map
*/
public void testSetMappedMap() {
final TestBean bean = new TestBean();
final Map<String, Object> map = new HashMap<>();
map.put("sub-key-1", "sub-value-1");
map.put("sub-key-2", "sub-value-2");
map.put("sub-key-3", "sub-value-3");
bean.getMapProperty().put("mappedMap", map);
assertEquals("BEFORE", "sub-value-3", ((Map<?, ?>) bean.getMapProperty().get("mappedMap")).get("sub-key-3"));
try {
PropertyUtils.setProperty(bean, "mapProperty(mappedMap)(sub-key-3)", "SUB-KEY-3-UPDATED");
} catch (final Throwable t) {
fail("Threw " + t + "");
}
assertEquals("AFTER", "SUB-KEY-3-UPDATED", ((Map<?, ?>) bean.getMapProperty().get("mappedMap")).get("sub-key-3"));
}
/**
* Test setting mapped values with periods in the key.
*/
public void testSetMappedPeriods() {
// -------- PropertyUtils.setMappedProperty()--------
bean.setMappedProperty("key.with.a.dot", "Special Value");
assertEquals("Can retrieve directly (A)", "Special Value", bean.getMappedProperty("key.with.a.dot"));
try {
PropertyUtils.setMappedProperty(bean, "mappedProperty", "key.with.a.dot", "Updated Special Value");
assertEquals("Check set via setMappedProperty", "Updated Special Value", bean.getMappedProperty("key.with.a.dot"));
} catch (final Exception e) {
fail("Thew exception: " + e);
}
// -------- PropertyUtils.setNestedProperty() --------
bean.setMappedProperty("key.with.a.dot", "Special Value");
assertEquals("Can retrieve directly (B)", "Special Value", bean.getMappedProperty("key.with.a.dot"));
try {
PropertyUtils.setNestedProperty(bean, "mappedProperty(key.with.a.dot)", "Updated Special Value");
assertEquals("Check set via setNestedProperty (B)", "Updated Special Value", bean.getMappedProperty("key.with.a.dot"));
} catch (final Exception e) {
fail("Thew exception: " + e);
}
// -------- PropertyUtils.setNestedProperty() --------
final TestBean testBean = new TestBean();
bean.setMappedObjects("nested.property", testBean);
assertEquals("Can retrieve directly (C)", "This is a string", testBean.getStringProperty());
try {
PropertyUtils.setNestedProperty(bean, "mappedObjects(nested.property).stringProperty", "Updated String Value");
assertEquals("Check set via setNestedProperty (C)", "Updated String Value", testBean.getStringProperty());
} catch (final Exception e) {
fail("Thew exception: " + e);
}
// -------- PropertyUtils.setNestedProperty() --------
bean.getNested().setMappedProperty("Mapped Key", "Nested Mapped Value");
try {
assertEquals("Can retrieve via getNestedProperty (D)", "Nested Mapped Value",
PropertyUtils.getNestedProperty(bean, "nested.mappedProperty(Mapped Key)"));
PropertyUtils.setNestedProperty(bean, "nested.mappedProperty(Mapped Key)", "Updated Nested Mapped Value");
assertEquals("Check set via setNestedProperty (D)", "Updated Nested Mapped Value",
PropertyUtils.getNestedProperty(bean, "nested.mappedProperty(Mapped Key)"));
} catch (final Exception e) {
fail("Thew exception: " + e);
}
}
/**
* Positive and negative tests on setMappedProperty valid arguments.
*/
public void testSetMappedValues() {
Object value = null;
// Use explicit key argument
try {
value = PropertyUtils.getMappedProperty(bean, "mappedProperty", "Fourth Key");
assertNull("Can not find fourth value", value);
} catch (final Throwable t) {
fail("Finding fourth value threw " + t);
}
try {
PropertyUtils.setMappedProperty(bean, "mappedProperty", "Fourth Key", "Fourth Value");
} catch (final Throwable t) {
fail("Setting fourth value threw " + t);
}
try {
value = PropertyUtils.getMappedProperty(bean, "mappedProperty", "Fourth Key");
assertEquals("Can find fourth value", "Fourth Value", value);
} catch (final Throwable t) {
fail("Finding fourth value threw " + t);
}
// Use key expression with parentheses
try {
value = PropertyUtils.getMappedProperty(bean, "mappedProperty(Fifth Key)");
assertNull("Can not find fifth value", value);
} catch (final Throwable t) {
fail("Finding fifth value threw " + t);
}
try {
PropertyUtils.setMappedProperty(bean, "mappedProperty(Fifth Key)", "Fifth Value");
} catch (final Throwable t) {
fail("Setting fifth value threw " + t);
}
try {
value = PropertyUtils.getMappedProperty(bean, "mappedProperty(Fifth Key)");
assertEquals("Can find fifth value", "Fifth Value", value);
} catch (final Throwable t) {
fail("Finding fifth value threw " + t);
}
// Use key expression with dotted expression
try {
value = PropertyUtils.getNestedProperty(bean, "mapProperty.Sixth Key");
assertNull("Can not find sixth value", value);
} catch (final Throwable t) {
fail("Finding fifth value threw " + t);
}
try {
PropertyUtils.setNestedProperty(bean, "mapProperty.Sixth Key", "Sixth Value");
} catch (final Throwable t) {
fail("Setting sixth value threw " + t);
}
try {
value = PropertyUtils.getNestedProperty(bean, "mapProperty.Sixth Key");
assertEquals("Can find sixth value", "Sixth Value", value);
} catch (final Throwable t) {
fail("Finding sixth value threw " + t);
}
}
/**
* Corner cases on setNestedProperty invalid arguments.
*/
public void testSetNestedArguments() {
try {
PropertyUtils.setNestedProperty(null, "stringProperty", "");
fail("Should throw IllegalArgumentException 1");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 1");
}
try {
PropertyUtils.setNestedProperty(bean, null, "");
fail("Should throw IllegalArgumentException 2");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 2");
}
}
/**
* Test setNextedProperty on a boolean property.
*/
public void testSetNestedBoolean() {
try {
final boolean oldValue = bean.getNested().getBooleanProperty();
final boolean newValue = !oldValue;
PropertyUtils.setNestedProperty(bean, "nested.booleanProperty", Boolean.valueOf(newValue));
assertTrue("Matched new value", newValue == bean.getNested().getBooleanProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test setNestedProperty on a double property.
*/
public void testSetNestedDouble() {
try {
final double oldValue = bean.getNested().getDoubleProperty();
final double newValue = oldValue + 1.0;
PropertyUtils.setNestedProperty(bean, "nested.doubleProperty", Double.valueOf(newValue));
assertEquals("Matched new value", newValue, bean.getNested().getDoubleProperty(), 0.005);
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test setNestedProperty on a float property.
*/
public void testSetNestedFloat() {
try {
final float oldValue = bean.getNested().getFloatProperty();
final float newValue = oldValue + (float) 1.0;
PropertyUtils.setNestedProperty(bean, "nested.floatProperty", Float.valueOf(newValue));
assertEquals("Matched new value", newValue, bean.getNested().getFloatProperty(), (float) 0.005);
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test setNestedProperty on a int property.
*/
public void testSetNestedInt() {
try {
final int oldValue = bean.getNested().getIntProperty();
final int newValue = oldValue + 1;
PropertyUtils.setNestedProperty(bean, "nested.intProperty", Integer.valueOf(newValue));
assertEquals("Matched new value", newValue, bean.getNested().getIntProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test setNestedProperty on a long property.
*/
public void testSetNestedLong() {
try {
final long oldValue = bean.getNested().getLongProperty();
final long newValue = oldValue + 1;
PropertyUtils.setNestedProperty(bean, "nested.longProperty", Long.valueOf(newValue));
assertEquals("Matched new value", newValue, bean.getNested().getLongProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test setNestedProperty on a read-only String property.
*/
public void testSetNestedReadOnly() {
try {
final String oldValue = bean.getNested().getWriteOnlyPropertyValue();
final String newValue = oldValue + " Extra Value";
PropertyUtils.setNestedProperty(bean, "nested.readOnlyProperty", newValue);
fail("Should have thrown NoSuchMethodException");
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
// Correct result for this test
}
}
/**
* Test setNestedProperty on a short property.
*/
public void testSetNestedShort() {
try {
final short oldValue = bean.getNested().getShortProperty();
short newValue = oldValue;
newValue++;
PropertyUtils.setNestedProperty(bean, "nested.shortProperty", Short.valueOf(newValue));
assertEquals("Matched new value", newValue, bean.getNested().getShortProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test setNestedProperty on a String property.
*/
public void testSetNestedString() {
try {
final String oldValue = bean.getNested().getStringProperty();
final String newValue = oldValue + " Extra Value";
PropertyUtils.setNestedProperty(bean, "nested.stringProperty", newValue);
assertEquals("Matched new value", newValue, bean.getNested().getStringProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test setNestedProperty on an unknown property name.
*/
public void testSetNestedUnknown() {
try {
final String newValue = "New String Value";
PropertyUtils.setNestedProperty(bean, "nested.unknown", newValue);
fail("Should have thrown NoSuchMethodException");
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
// Correct result for this test
}
}
/**
* Test setNestedProperty on a write-only String property.
*/
public void testSetNestedWriteOnly() {
try {
final String oldValue = bean.getNested().getWriteOnlyPropertyValue();
final String newValue = oldValue + " Extra Value";
PropertyUtils.setNestedProperty(bean, "nested.writeOnlyProperty", newValue);
assertEquals("Matched new value", newValue, bean.getNested().getWriteOnlyPropertyValue());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
public void testSetNoGetter() throws Exception {
final BetaBean bean = new BetaBean("Cedric");
// test standard no getter
bean.setNoGetterProperty("Sigma");
assertEquals("BetaBean test failed", "Sigma", bean.getSecret());
assertNotNull("Descriptor is null", PropertyUtils.getPropertyDescriptor(bean, "noGetterProperty"));
BeanUtils.setProperty(bean, "noGetterProperty", "Omega");
assertEquals("Cannot set no-getter property", "Omega", bean.getSecret());
// test mapped no getter descriptor
assertNotNull("Map Descriptor is null", PropertyUtils.getPropertyDescriptor(bean, "noGetterMappedProperty"));
PropertyUtils.setMappedProperty(bean, "noGetterMappedProperty", "Epsilon", "Epsilon");
assertEquals("Cannot set mapped no-getter property", "MAP:Epsilon", bean.getSecret());
}
/**
* Test accessing a public sub-bean of a package scope bean
*/
public void testSetPublicSubBean_of_PackageBean() {
final PublicSubBean bean = new PublicSubBean();
bean.setFoo("foo-start");
bean.setBar("bar-start");
// Set Foo
try {
PropertyUtils.setProperty(bean, "foo", "foo-updated");
} catch (final Throwable t) {
fail("setProperty(foo) threw " + t);
}
assertEquals("foo property", "foo-updated", bean.getFoo());
// Set Bar
try {
PropertyUtils.setProperty(bean, "bar", "bar-updated");
} catch (final Throwable t) {
fail("setProperty(bar) threw " + t);
}
assertEquals("bar property", "bar-updated", bean.getBar());
}
/**
* Corner cases on setSimpleProperty invalid arguments.
*/
public void testSetSimpleArguments() {
try {
PropertyUtils.setSimpleProperty(null, "stringProperty", "");
fail("Should throw IllegalArgumentException 1");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 1");
}
try {
PropertyUtils.setSimpleProperty(bean, null, "");
fail("Should throw IllegalArgumentException 2");
} catch (final IllegalArgumentException e) {
// Expected response
} catch (final Throwable t) {
fail("Threw " + t + " instead of IllegalArgumentException 2");
}
}
/**
* Test setSimpleProperty on a boolean property.
*/
public void testSetSimpleBoolean() {
try {
final boolean oldValue = bean.getBooleanProperty();
final boolean newValue = !oldValue;
PropertyUtils.setSimpleProperty(bean, "booleanProperty", Boolean.valueOf(newValue));
assertTrue("Matched new value", newValue == bean.getBooleanProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test setSimpleProperty on a double property.
*/
public void testSetSimpleDouble() {
try {
final double oldValue = bean.getDoubleProperty();
final double newValue = oldValue + 1.0;
PropertyUtils.setSimpleProperty(bean, "doubleProperty", Double.valueOf(newValue));
assertEquals("Matched new value", newValue, bean.getDoubleProperty(), 0.005);
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test setSimpleProperty on a float property.
*/
public void testSetSimpleFloat() {
try {
final float oldValue = bean.getFloatProperty();
final float newValue = oldValue + (float) 1.0;
PropertyUtils.setSimpleProperty(bean, "floatProperty", Float.valueOf(newValue));
assertEquals("Matched new value", newValue, bean.getFloatProperty(), (float) 0.005);
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Negative test setSimpleProperty on an indexed property.
*/
public void testSetSimpleIndexed() {
try {
PropertyUtils.setSimpleProperty(bean, "stringIndexed[0]", "New String Value");
fail("Should have thrown IllegalArgumentException");
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
// Correct result for this test
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test setSimpleProperty on a int property.
*/
public void testSetSimpleInt() {
try {
final int oldValue = bean.getIntProperty();
final int newValue = oldValue + 1;
PropertyUtils.setSimpleProperty(bean, "intProperty", Integer.valueOf(newValue));
assertEquals("Matched new value", newValue, bean.getIntProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test setSimpleProperty on a long property.
*/
public void testSetSimpleLong() {
try {
final long oldValue = bean.getLongProperty();
final long newValue = oldValue + 1;
PropertyUtils.setSimpleProperty(bean, "longProperty", Long.valueOf(newValue));
assertEquals("Matched new value", newValue, bean.getLongProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Negative test setSimpleProperty on a nested property.
*/
public void testSetSimpleNested() {
try {
PropertyUtils.setSimpleProperty(bean, "nested.stringProperty", "New String Value");
fail("Should have thrown IllegalArgumentException");
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
// Correct result for this test
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test setSimpleProperty on a read-only String property.
*/
public void testSetSimpleReadOnly() {
try {
final String oldValue = bean.getWriteOnlyPropertyValue();
final String newValue = oldValue + " Extra Value";
PropertyUtils.setSimpleProperty(bean, "readOnlyProperty", newValue);
fail("Should have thrown NoSuchMethodException");
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
// Correct result for this test
assertEquals("Property 'readOnlyProperty' has no setter method in class '" + bean.getClass() + "'", e.getMessage());
}
}
/**
* Test setSimpleProperty on a short property.
*/
public void testSetSimpleShort() {
try {
final short oldValue = bean.getShortProperty();
short newValue = oldValue;
newValue++;
PropertyUtils.setSimpleProperty(bean, "shortProperty", Short.valueOf(newValue));
assertEquals("Matched new value", newValue, bean.getShortProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test setSimpleProperty on a String property.
*/
public void testSetSimpleString() {
try {
final String oldValue = bean.getStringProperty();
final String newValue = oldValue + " Extra Value";
PropertyUtils.setSimpleProperty(bean, "stringProperty", newValue);
assertEquals("Matched new value", newValue, bean.getStringProperty());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* Test setSimpleProperty on an unknown property name.
*/
public void testSetSimpleUnknown() {
try {
final String newValue = "New String Value";
PropertyUtils.setSimpleProperty(bean, "unknown", newValue);
fail("Should have thrown NoSuchMethodException");
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
// Correct result for this test
assertEquals("Unknown property 'unknown' on class '" + bean.getClass() + "'", e.getMessage());
}
}
/**
* Test setSimpleProperty on a write-only String property.
*/
public void testSetSimpleWriteOnly() {
try {
final String oldValue = bean.getWriteOnlyPropertyValue();
final String newValue = oldValue + " Extra Value";
PropertyUtils.setSimpleProperty(bean, "writeOnlyProperty", newValue);
assertEquals("Matched new value", newValue, bean.getWriteOnlyPropertyValue());
} catch (final IllegalAccessException e) {
fail("IllegalAccessException");
} catch (final IllegalArgumentException e) {
fail("IllegalArgumentException");
} catch (final InvocationTargetException e) {
fail("InvocationTargetException");
} catch (final NoSuchMethodException e) {
fail("NoSuchMethodException");
}
}
/**
* When a bean has a null property which is reference by the standard access language, this should throw a NestedNullException.
*/
public void testThrowNestedNull() throws Exception {
final NestedTestBean nestedBean = new NestedTestBean("base");
// don't init!
try {
PropertyUtils.getProperty(nestedBean, "simpleBeanProperty.indexedProperty[0]");
fail("NestedNullException not thrown");
} catch (final NestedNullException e) {
// that's what we wanted!
}
}
}