View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.beanutils2;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.assertInstanceOf;
22  import static org.junit.jupiter.api.Assertions.assertNotSame;
23  import static org.junit.jupiter.api.Assertions.assertSame;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  
26  import java.io.ByteArrayInputStream;
27  import java.io.ByteArrayOutputStream;
28  import java.io.IOException;
29  import java.io.NotSerializableException;
30  import java.io.ObjectInputStream;
31  import java.io.ObjectOutputStream;
32  
33  import org.junit.jupiter.api.AfterEach;
34  import org.junit.jupiter.api.BeforeEach;
35  import org.junit.jupiter.api.Test;
36  
37  /**
38   * <p>
39   * Test Case for the {@code WrapDynaBean} implementation class. These tests were based on the ones in {@code PropertyUtilsTestCase} because the two classes
40   * provide similar levels of functionality.
41   * </p>
42   */
43  public class WrapDynaBeanTest extends BasicDynaBeanTest {
44  
45      /**
46       * Helper method for testing whether basic access to properties works as expected.
47       */
48      private void checkSimplePropertyAccess() {
49          // Invalid getter
50          assertThrows(IllegalArgumentException.class, () -> bean.get("invalidProperty"));
51  
52          // Invalid setter
53          assertThrows(IllegalArgumentException.class, () -> bean.set("invalidProperty", "XYZ"));
54  
55          // Set up initial Value
56          String testValue = "Original Value";
57          final String testProperty = "stringProperty";
58          final TestBean instance = (TestBean) ((WrapDynaBean) bean).getInstance();
59          instance.setStringProperty(testValue);
60          assertEquals(testValue, instance.getStringProperty(), "Check String property");
61  
62          // Test Valid Get & Set
63          testValue = "Some new value";
64          bean.set(testProperty, testValue);
65          assertEquals(testValue, instance.getStringProperty(), "Test Set");
66          assertEquals(testValue, bean.get(testProperty), "Test Get");
67      }
68  
69      /**
70       * Do serialization and deserialization.
71       */
72      private Object serializeDeserialize(final Object target, final String text) throws IOException, ClassNotFoundException {
73          // Serialize the test object
74          final ByteArrayOutputStream baos = new ByteArrayOutputStream();
75          try (final ObjectOutputStream oos = new ObjectOutputStream(baos)) {
76              oos.writeObject(target);
77              oos.flush();
78          }
79          // Deserialize the test object
80          Object result = null;
81          try (final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
82                  final ObjectInputStream ois = new ObjectInputStream(bais)) {
83              result = ois.readObject();
84          }
85          return result;
86      }
87  
88      /**
89       * Sets up instance variables required by this test case.
90       */
91      @Override
92      @BeforeEach
93      public void setUp() throws Exception {
94          bean = new WrapDynaBean(new TestBean());
95      }
96  
97      /**
98       * Tear down instance variables required by this test case.
99       */
100     @Override
101     @AfterEach
102     public void tearDown() {
103         bean = null;
104     }
105 
106     /** Tests getInstance method */
107     @Test
108     public void testGetInstance() {
109         final AlphaBean alphaBean = new AlphaBean("Now On Air... John Peel");
110         final WrapDynaBean dynaBean = new WrapDynaBean(alphaBean);
111         final Object wrappedInstance = dynaBean.getInstance();
112         assertInstanceOf(AlphaBean.class, wrappedInstance, "Object type is AlphaBean");
113         final AlphaBean wrappedAlphaBean = (AlphaBean) wrappedInstance;
114         assertSame(wrappedAlphaBean, alphaBean, "Same Object");
115     }
116 
117     /**
118      * Tests whether caching works for WrapDynaClass objects.
119      */
120     @Test
121     public void testGetWrapDynaClassFromCache() {
122         final WrapDynaClass clazz = WrapDynaClass.createDynaClass(TestBean.class);
123         assertSame(clazz, WrapDynaClass.createDynaClass(TestBean.class), "Instance not cached");
124     }
125 
126     /**
127      * Tests whether the PropertyUtilsBean instance associated with a WrapDynaClass is taken into account when accessing an instance from the cache.
128      */
129     @Test
130     public void testGetWrapDynaClassFromCacheWithPropUtils() {
131         final WrapDynaClass clazz = WrapDynaClass.createDynaClass(TestBean.class);
132         final PropertyUtilsBean pu = new PropertyUtilsBean();
133         final WrapDynaClass clazz2 = WrapDynaClass.createDynaClass(TestBean.class, pu);
134         assertNotSame(clazz, clazz2, "Got same instance from cache");
135     }
136 
137     /**
138      * The {@code set()} method.
139      */
140     @Test
141     public void testIndexedProperties() {
142 
143         // Invalid getter
144         assertThrows(IllegalArgumentException.class, () -> bean.get("invalidProperty", 0));
145 
146         // Invalid setter
147         assertThrows(IllegalArgumentException.class, () -> bean.set("invalidProperty", 0, "XYZ"));
148 
149         // Set up initial Value
150         String testValue = "Original Value";
151         final String testProperty = "stringIndexed";
152         final TestBean instance = (TestBean) ((WrapDynaBean) bean).getInstance();
153         instance.setStringIndexed(0, testValue);
154         assertEquals(testValue, instance.getStringIndexed(0), "Check String property");
155 
156         // Test Valid Get & Set
157         testValue = "Some new value";
158         bean.set(testProperty, 0, testValue);
159         assertEquals(testValue, instance.getStringIndexed(0), "Test Set");
160         assertEquals(testValue, bean.get(testProperty, 0), "Test Get");
161     }
162 
163     /**
164      * Tests whether a WrapDynaClass can be provided when constructing a bean.
165      */
166     @Test
167     public void testInitWithDynaClass() {
168         final WrapDynaClass clazz = WrapDynaClass.createDynaClass(TestBean.class);
169         bean = new WrapDynaBean(new TestBean(), clazz);
170         assertSame(clazz, bean.getDynaClass(), "Wrong DynaClass");
171         checkSimplePropertyAccess();
172     }
173 
174     /**
175      * Tests whether a custom PropertyUtilsBean instance can be used for introspection of bean properties.
176      */
177     @Test
178     public void testIntrospectionWithCustomPropUtils() {
179         final PropertyUtilsBean pu = new PropertyUtilsBean();
180         pu.addBeanIntrospector(new FluentPropertyBeanIntrospector());
181         final WrapDynaClass dynaClass = WrapDynaClass.createDynaClass(FluentIntrospectionTestBean.class, pu);
182         final FluentIntrospectionTestBean obj = new FluentIntrospectionTestBean();
183         bean = new WrapDynaBean(obj, dynaClass);
184         bean.set("fluentProperty", "testvalue");
185         assertEquals("testvalue", obj.getStringProperty(), "Property not set");
186     }
187 
188     /**
189      * The {@code contains()} method is not supported by the {@code WrapDynaBean} implementation class.
190      */
191     @Override
192     @Test
193     public void testMappedContains() {
194         assertThrows(UnsupportedOperationException.class, () -> bean.contains("mappedProperty", "First Key"));
195         assertThrows(UnsupportedOperationException.class, () -> bean.contains("mappedProperty", "Unknown Key"));
196     }
197 
198     /**
199      * The {@code remove()} method is not supported by the {@code WrapDynaBean} implementation class.
200      */
201     @Override
202     @Test
203     public void testMappedRemove() {
204 
205         assertThrows(UnsupportedOperationException.class, () -> bean.contains("mappedProperty", "First Key"));
206         assertThrows(UnsupportedOperationException.class, () -> bean.remove("mappedProperty", "First Key"));
207 
208         assertThrows(UnsupportedOperationException.class, () -> bean.contains("mappedProperty", "Unknown Key"));
209         assertThrows(UnsupportedOperationException.class, () -> bean.remove("mappedProperty", "Unknown Key"));
210 
211     }
212 
213     /** Tests the newInstance implementation for WrapDynaClass */
214     @Test
215     public void testNewInstance() throws Exception {
216         final WrapDynaClass dynaClass = WrapDynaClass.createDynaClass(AlphaBean.class);
217         final Object createdInstance = dynaClass.newInstance();
218         assertInstanceOf(WrapDynaBean.class, createdInstance, "Object type is WrapDynaBean");
219         final WrapDynaBean dynaBean = (WrapDynaBean) createdInstance;
220         assertInstanceOf(AlphaBean.class, dynaBean.getInstance(), "Object type is AlphaBean");
221     }
222 
223     /**
224      * Serialization and deserialization tests. (WrapDynaBean is now serializable, although WrapDynaClass still is not)
225      */
226     @Override
227     @Test
228     public void testNotSerializableException() throws Exception {
229         // Create a bean and set a value
230         final WrapDynaBean origBean = new WrapDynaBean(new TestBean());
231         final Integer newValue = Integer.valueOf(789);
232         assertEquals(Integer.valueOf(123), origBean.get("intProperty"), "origBean default");
233         origBean.set("intProperty", newValue);
234         assertEquals(newValue, origBean.get("intProperty"), "origBean new value");
235         // Serialize/Deserialize & test value
236         assertThrows(NotSerializableException.class, () -> serializeDeserialize(origBean, "First Test"));
237     }
238 
239     /**
240      * The {@code set()} method.
241      */
242     @Test
243     public void testSimpleProperties() {
244 
245         checkSimplePropertyAccess();
246 
247     }
248 }