View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */ 
17  
18  
19  package org.apache.commons.beanutils;
20  
21  
22  import java.math.BigDecimal;
23  import java.sql.ResultSet;
24  import java.sql.ResultSetMetaData;
25  import java.sql.SQLException;
26  import java.util.List;
27  
28  import junit.framework.Test;
29  import junit.framework.TestCase;
30  import junit.framework.TestSuite;
31  
32  
33  /**
34   * Test accessing RowSets via DynaBeans.
35   *
36   * @author Craig R. McClanahan
37   * @version $Revision: 745074 $ $Date: 2009-02-17 09:00:58 -0500 (Tue, 17 Feb 2009) $
38   */
39  
40  public class DynaRowSetTestCase extends TestCase {
41  
42  
43      // ----------------------------------------------------- Instance Variables
44  
45  
46      /**
47       * The mock result set DynaClass to be tested.
48       */
49      protected RowSetDynaClass dynaClass = null;
50  
51  
52      /**
53       * Names of the columns for this test.  Must match the order they are
54       * defined in {@link TestResultSetMetaData}, and must be all lower case.
55       */
56      protected String columns[] =
57      { "bigdecimalproperty", "booleanproperty",
58        "byteproperty", "dateproperty",
59        "doubleproperty", "floatproperty",
60        "intproperty", "longproperty",
61        "nullproperty", "shortproperty",
62        "stringproperty", "timeproperty",
63        "timestampproperty" };
64  
65  
66      // ----------------------------------------------------------- Constructors
67  
68  
69      /**
70       * Construct a new instance of this test case.
71       *
72       * @param name Name of the test case
73       */
74      public DynaRowSetTestCase(String name) {
75  
76          super(name);
77  
78      }
79  
80  
81      // --------------------------------------------------- Overall Test Methods
82  
83  
84      /**
85       * Set up instance variables required by this test case.
86       */
87      public void setUp() throws Exception {
88  
89          dynaClass = new RowSetDynaClass(TestResultSet.createProxy());
90  
91      }
92  
93  
94      /**
95       * Return the tests included in this test suite.
96       */
97      public static Test suite() {
98  
99          return (new TestSuite(DynaRowSetTestCase.class));
100 
101     }
102 
103 
104     /**
105      * Tear down instance variables required by this test case.
106      */
107     public void tearDown() {
108 
109         dynaClass = null;
110 
111     }
112 
113 
114 
115     // ------------------------------------------------ Individual Test Methods
116 
117 
118     public void testGetName() {
119 
120         assertEquals("DynaClass name",
121                      "org.apache.commons.beanutils.RowSetDynaClass",
122                      dynaClass.getName());
123 
124 
125     }
126 
127 
128     public void testGetDynaProperty() {
129 
130         // Invalid argument test
131         try {
132             dynaClass.getDynaProperty(null);
133             fail("Did not throw IllegaArgumentException");
134         } catch (IllegalArgumentException e) {
135             // Expected result
136         }
137 
138         // Negative test
139         DynaProperty dynaProp = dynaClass.getDynaProperty("unknownProperty");
140         assertTrue("unknown property returns null",
141                    (dynaProp == null));
142 
143         // Positive test
144         dynaProp = dynaClass.getDynaProperty("stringproperty");
145         assertNotNull("string property exists", dynaProp);
146         assertEquals("string property name", "stringproperty",
147                      dynaProp.getName());
148         assertEquals("string property class", String.class,
149                      dynaProp.getType());
150 
151     }
152 
153 
154     public void testGetDynaProperties() {
155 
156         DynaProperty dynaProps[] = dynaClass.getDynaProperties();
157         assertNotNull("dynaProps exists", dynaProps);
158         assertEquals("dynaProps length", columns.length, dynaProps.length);
159         for (int i = 0; i < columns.length; i++) {
160             assertEquals("Property " + columns[i],
161                          columns[i], dynaProps[i].getName());
162         }
163 
164     }
165 
166 
167     public void testNewInstance() {
168 
169         try {
170             dynaClass.newInstance();
171             fail("Did not throw UnsupportedOperationException()");
172         } catch (UnsupportedOperationException e) {
173             // Expected result
174         } catch (Exception e) {
175             fail("Threw exception " + e);
176         }
177 
178     }
179 
180 
181     public void testListCount() {
182 
183         List rows = dynaClass.getRows();
184         assertNotNull("list exists", rows);
185         assertEquals("list row count", 5, rows.size());
186 
187     }
188 
189 
190     public void testListResults() {
191 
192         // Grab the third row
193         List rows = dynaClass.getRows();
194         DynaBean row = (DynaBean) rows.get(2);
195 
196         // Invalid argument test
197         try {
198             row.get("unknownProperty");
199             fail("Did not throw IllegalArgumentException");
200         } catch (IllegalArgumentException e) {
201             // Expected result
202         }
203 
204         // Verify property values
205 
206         Object bigDecimalProperty = row.get("bigdecimalproperty");
207         assertNotNull("bigDecimalProperty exists", bigDecimalProperty);
208         assertTrue("bigDecimalProperty type",
209                    bigDecimalProperty instanceof BigDecimal);
210         assertEquals("bigDecimalProperty value",
211                      123.45,
212                      ((BigDecimal) bigDecimalProperty).doubleValue(),
213                      0.005);
214 
215         Object intProperty = row.get("intproperty");
216         assertNotNull("intProperty exists", intProperty);
217         assertTrue("intProperty type",
218                    intProperty instanceof Integer);
219         assertEquals("intProperty value",
220                      103,
221                      ((Integer) intProperty).intValue());
222 
223         Object nullProperty = row.get("nullproperty");
224         assertNull("nullProperty null", nullProperty);
225 
226         Object stringProperty = row.get("stringproperty");
227         assertNotNull("stringProperty exists", stringProperty);
228         assertTrue("stringProperty type",
229                    stringProperty instanceof String);
230         assertEquals("stringProperty value",
231                      "This is a string",
232                      (String) stringProperty);
233 
234 
235     }
236 
237     /**
238      * Test normal case column names (i.e. not converted to lower case)
239      */
240     public void testListResultsNormalCase() {
241         RowSetDynaClass dynaClass = null;
242         try {
243             dynaClass = new RowSetDynaClass(TestResultSet.createProxy(), false);
244         } catch (Exception e) {
245             fail("Error creating RowSetDynaClass: " + e);
246         }
247 
248         // Grab the third row
249         List rows = dynaClass.getRows();
250         DynaBean row = (DynaBean) rows.get(2);
251 
252         // Invalid argument test
253         try {
254             row.get("unknownProperty");
255             fail("Did not throw IllegalArgumentException");
256         } catch (IllegalArgumentException e) {
257             // Expected result
258         }
259 
260         // Verify property values
261 
262         Object bigDecimalProperty = row.get("bigDecimalProperty");
263         assertNotNull("bigDecimalProperty exists", bigDecimalProperty);
264         assertTrue("bigDecimalProperty type",
265                    bigDecimalProperty instanceof BigDecimal);
266         assertEquals("bigDecimalProperty value",
267                      123.45,
268                      ((BigDecimal) bigDecimalProperty).doubleValue(),
269                      0.005);
270 
271         Object intProperty = row.get("intProperty");
272         assertNotNull("intProperty exists", intProperty);
273         assertTrue("intProperty type",
274                    intProperty instanceof Integer);
275         assertEquals("intProperty value",
276                      103,
277                      ((Integer) intProperty).intValue());
278 
279         Object nullProperty = row.get("nullProperty");
280         assertNull("nullProperty null", nullProperty);
281 
282         Object stringProperty = row.get("stringProperty");
283         assertNotNull("stringProperty exists", stringProperty);
284         assertTrue("stringProperty type",
285                    stringProperty instanceof String);
286         assertEquals("stringProperty value",
287                      "This is a string",
288                      (String) stringProperty);
289 
290 
291     }
292 
293     public void testLimitedRows() throws Exception {
294         
295         // created one with low limit
296         RowSetDynaClass limitedDynaClass = new RowSetDynaClass(TestResultSet.createProxy(), 3);
297         List rows = limitedDynaClass.getRows();
298         assertNotNull("list exists", rows);
299         assertEquals("limited row count", 3, rows.size());
300         
301     }
302 
303     /**
304      * Test issues associated with Oracle JDBC driver.
305      * 
306      * See issue# https://issues.apache.org/jira/browse/BEANUTILS-142
307      * 
308      * @throws Exception if an error occurs
309      */
310     public void testInconsistentOracleDriver() throws Exception {
311 
312         ResultSetMetaData metaData = TestResultSetMetaData.createProxy(new TestResultSetMetaDataInconsistent());
313         ResultSet resultSet = TestResultSet.createProxy(new TestResultSetInconsistent(metaData));
314 
315         // Date Column returns "java.sql.Timestamp" for the column class name but ResultSet getObject
316         // returns a java.sql.Date value
317         int dateColIdx = 4;
318         assertEquals("Date Meta Name",       "dateProperty",       metaData.getColumnName(dateColIdx));
319         assertEquals("Date Meta Class",      "java.sql.Timestamp", metaData.getColumnClassName(dateColIdx));
320         assertEquals("Date Meta Type",       java.sql.Types.DATE,  metaData.getColumnType(dateColIdx));
321         assertEquals("Date ResultSet Value", java.sql.Date.class,  resultSet.getObject("dateProperty").getClass());
322 
323         // Timestamp column class returns a custom Timestamp impl for the column class name and ResultSet getObject
324         int timestampColIdx = 13;
325         assertEquals("Timestamp Meta Name",       "timestampProperty",             metaData.getColumnName(timestampColIdx));
326         assertEquals("Timestamp Meta Class",      CustomTimestamp.class.getName(), metaData.getColumnClassName(timestampColIdx));
327         assertEquals("Timestamp Meta Type",       java.sql.Types.TIMESTAMP,        metaData.getColumnType(timestampColIdx));
328         assertEquals("Timestamp ResultSet Value", CustomTimestamp.class,           resultSet.getObject("timestampProperty").getClass());
329 
330         RowSetDynaClass inconsistentDynaClass = new RowSetDynaClass(resultSet);
331         DynaBean firstRow = (DynaBean)inconsistentDynaClass.getRows().get(0);
332         Class expectedType = null;
333         DynaProperty property = null;
334         
335         // Test Date
336         property = firstRow.getDynaClass().getDynaProperty("dateproperty");
337         expectedType = java.sql.Date.class;
338         assertEquals("Date Class", expectedType, property.getType());
339         assertEquals("Date Value", expectedType, firstRow.get(property.getName()).getClass());
340 
341         // Test Timestamp
342         property = firstRow.getDynaClass().getDynaProperty("timestampproperty");
343         expectedType = java.sql.Timestamp.class;
344         assertEquals("Timestamp Class", expectedType, property.getType());
345         assertEquals("Timestamp Value", expectedType, firstRow.get(property.getName()).getClass());
346     }
347 
348     /**
349      * A proxy ResultSet implementation that returns Timstamp for a date column.
350      *
351      * See issue# https://issues.apache.org/jira/browse/BEANUTILS-142 
352      */
353     private static class TestResultSetInconsistent extends  TestResultSet {
354 
355         public TestResultSetInconsistent(ResultSetMetaData metaData) {
356             super(metaData);
357         }
358         /**
359          * Get an columns's value
360          * @param columnName Name of the column
361          * @return the column value
362          * @throws SQLException if an error occurs
363          */
364         public Object getObject(String columnName) throws SQLException {
365             if ("timestampProperty".equals(columnName)) {
366                 return new CustomTimestamp();
367             } else {
368                 return super.getObject(columnName);
369             }
370         }
371 
372     }
373 
374     /**
375      * A proxy ResultSetMetaData implementation that returns a class name that
376      * is inconsistent with the type returned by the ResultSet.getObject() method.
377      *
378      * See issue# https://issues.apache.org/jira/browse/BEANUTILS-142 
379      */
380     private static class TestResultSetMetaDataInconsistent extends  TestResultSetMetaData {
381 
382         /**
383          * This method substitues class names of "java.sql.Timestamp" with
384          * "java.sql.Date" to test inconsistent JDBC drivers.
385          *
386          * @param columnIndex The column index
387          * @return The column class name
388          * @throws SQLException if an error occurs
389          */
390         public String getColumnClassName(int columnIndex) throws SQLException {
391             String columnName = getColumnName(columnIndex);
392             if (columnName.equals("dateProperty")) {
393                 return java.sql.Timestamp.class.getName();
394             } else if (columnName.equals("timestampProperty")) {
395                 return CustomTimestamp.class.getName();
396             } else {
397                 return super.getColumnClassName(columnIndex);
398             }
399         }
400     }
401     private static class CustomTimestamp {
402         private long timestamp = new java.util.Date().getTime();
403         public String toString() {
404             return "CustomTimestamp[" + timestamp + "]";
405         }
406     }
407 }