PageRenderTime 54ms CodeModel.GetById 14ms app.highlight 34ms RepoModel.GetById 1ms app.codeStats 0ms

/src/tests/net/sf/persist/tests/framework/BeanTest.java

http://github.com/rufiao/persist
Java | 353 lines | 205 code | 70 blank | 78 comment | 26 complexity | 0fd7647d6ad347f7f5cd48b810a77462 MD5 | raw file
  1
  2// $Id$
  3
  4package net.sf.persist.tests.framework;
  5
  6import static org.junit.Assert.assertEquals;
  7import static org.junit.Assert.assertNotNull;
  8import static org.junit.Assert.assertNull;
  9import static org.junit.Assert.assertTrue;
 10
 11import java.sql.Connection;
 12import java.sql.SQLException;
 13import java.util.List;
 14import java.util.Map;
 15
 16import net.sf.persist.Persist;
 17import net.sf.persist.Result;
 18import net.sf.persist.TableMapping;
 19import net.sf.persist.tests.common.Simple;
 20import net.sf.persist.tests.common.TestSimple;
 21
 22public class BeanTest {
 23	
 24	// TODO: test updates passing a single value
 25	
 26	public static void test(Persist persist, BeanMap beanMap) {
 27		Connection connection = persist.getConnection();
 28		Class cls = DynamicBean.createBeanClass(beanMap, false);
 29		Class clsNoTable = DynamicBean.createBeanClass(beanMap, true);
 30		
 31		String tableName = dbName(beanMap.getClassName());
 32		
 33		try {
 34			connection.createStatement().execute("delete from " + tableName);
 35		} catch (SQLException e) {
 36			throw new RuntimeException(e);
 37		}
 38		BeanTest.testAll(persist, cls, clsNoTable, beanMap);	
 39		
 40
 41		try {
 42			connection.createStatement().execute("delete from " + tableName);
 43		} catch (SQLException e) {
 44			throw new RuntimeException(e);
 45		}
 46		BeanTest.testAllNull(persist, cls, clsNoTable, beanMap);
 47		
 48		if (beanMap.supportsAutoGeneratedKeys()) {
 49			testExecuteUpdateAutoGeneratedKeys(persist);
 50			testSetAutoGeneratedKeys(persist);
 51		}
 52
 53	}
 54	
 55	/**
 56	 * Perform tests using a bean with non-null values
 57	 */
 58	public static void testAll(Persist persist, Class cls, Class clsNoTable, BeanMap beanMap) {
 59		persist.setAutoCommit(false);
 60		Object obj = DynamicBean.createInstance(cls, beanMap, false);
 61		BeanTest.testInsert(persist, obj, beanMap);
 62		BeanTest.testSelectByFields(persist, obj, beanMap);
 63		BeanTest.testSelectFields(persist, obj, beanMap, false);
 64		BeanTest.testSelectMap(persist, obj, beanMap);
 65		BeanTest.testReadNoTable(persist, obj, clsNoTable);
 66		persist.commit();
 67		persist.setAutoCommit(true);
 68	}
 69
 70	/**
 71	 * Perform tests using a bean with null values
 72	 */
 73	public static void testAllNull(Persist persist, Class cls, Class clsNoTable, BeanMap beanMap) {
 74		persist.setAutoCommit(false);
 75		Object objNull = DynamicBean.createInstance(cls, beanMap, true);
 76		BeanTest.testInsert(persist, objNull, beanMap);
 77		BeanTest.testSelectByFieldsNull(persist, objNull, beanMap);
 78		BeanTest.testSelectFields(persist, objNull, beanMap, true);
 79		BeanTest.testSelectMap(persist, objNull, beanMap);
 80		BeanTest.testReadNoTable(persist, objNull, clsNoTable);
 81		persist.commit();
 82		persist.setAutoCommit(true);
 83	}
 84	
 85	/**
 86	 * tests insertion of a bean
 87	 */
 88	public static void testInsert(Persist persist, Object obj, BeanMap beanMap) {
 89		Class cls = obj.getClass();
 90		String tableName = dbName(obj.getClass().getSimpleName());
 91		
 92		// perform insert
 93		persist.insert(obj);
 94		
 95		// check if a single result exists in the table (expects the table to be clean by the beginning of the process)
 96		String sql = "select * from " + tableName;
 97		List read = persist.readList(cls, sql);
 98		if (read.size()!=1) {
 99			throw new AssertionError("Expected 1 result but got [" + read.size() + "] as result of sql [" + sql + "]");
100		}
101		
102		// check if the bean read is the same as inserted
103		if (!obj.equals(read.get(0))) { 
104			throw new AssertionError("Expected [" + DynamicBean.toString(obj) + "] but got [" 
105					+ DynamicBean.toString(read.get(0)) + "] as result of [" + sql + "]");
106		}
107	}
108	
109	/**
110	 * tests reading with NoTable class
111	 */
112	public static void testReadNoTable(Persist persist, Object obj, Class clsNoTable) {
113		
114		String tableName = dbName(obj.getClass().getSimpleName());
115		
116		// now read with NoTable (assumes previously inserted data)
117		Object objNoTable = persist.read(clsNoTable, "select * from " + tableName);
118		
119		// compare values
120		if (!DynamicBean.compareBeansFromDifferentClasses(obj, objNoTable)) {
121			throw new AssertionError("Expected [" + DynamicBean.toString(obj) + "] but got [" 
122					+ DynamicBean.toString(objNoTable) + "]");
123		}
124	}	
125		
126	/**
127	 * For each field and each field type, execute a query in the format
128	 * select * from tableName where columnName=?
129	 */
130	public static void testSelectByFields(Persist persist, Object obj, BeanMap beanMap) {
131		Class cls = obj.getClass();
132		String tableName = dbName(obj.getClass().getSimpleName());
133		
134		// for each field in the bean
135		for (FieldMap fieldMap : beanMap.getFields()) {
136			
137			// only perform tests if the field supports queries by value (blobs in oracle, for instance, don't)
138			if (fieldMap.isSupportsQueryByValue()) {
139				String columnName = dbName(fieldMap.getFieldName());
140				String sql = "select * from " + tableName + " where " + columnName + "=?";
141				Object fieldValue = DynamicBean.getFieldValue(obj, fieldMap.getFieldName());
142				
143				// for each type supported by the field, test if a query using an object of that type returns data correctly
144				for (Class fieldType : fieldMap.getTypes()) {
145					
146					// use value converted to the type being tested
147					Object fieldValueConverted = DynamicBean.convertToType(fieldType, fieldValue);
148					
149					// query using the type being tested
150					Object ret = persist.read(cls, sql, fieldValueConverted);
151					
152					// check if the result is not null and has the same data as the object being tested
153					if (ret==null) {
154						throw new AssertionError("Expected not null value but got null as result of [" + sql 
155								+ "] with parameter [" + fieldValue + "]");
156					}
157					if (!obj.equals(ret)) {
158						throw new AssertionError("Expected [" + DynamicBean.toString(obj) + "] but got [" 
159								+ DynamicBean.toString(ret) + "] as result of [" + sql + "]");
160					}
161				}
162			}
163		}
164	}
165	
166	/**
167	 * For each field, execute a query in the format
168	 * select * from tableName where columnName is null
169	 */
170	public static void testSelectByFieldsNull(Persist persist, Object obj, BeanMap beanMap) {
171		Class cls = obj.getClass();
172		String tableName = dbName(obj.getClass().getSimpleName());
173		
174		// for each field in the bean
175		for (FieldMap fieldMap : beanMap.getFields()) {
176			
177			// only perform tests if the field supports queries by value (blobs in oracle, for instance, don't)
178			if (fieldMap.isSupportsQueryByValue()) {
179				String columnName = dbName(fieldMap.getFieldName());
180				
181				// test if query for null value in the column related with the field return the object correctly
182				String sql = "select * from " + tableName + " where " + columnName + " is null";
183				Object ret = persist.read(cls, sql);
184				if (ret==null) throw new AssertionError("Expected not null value but got null as result of [" + sql + "]");
185				if (!obj.equals(ret)) {
186					throw new AssertionError("Expected [" + DynamicBean.toString(obj) + "] but got [" 
187							+ DynamicBean.toString(ret) + "] as result of [" + sql + "]");
188				}
189			}
190		}
191	}
192	
193	/**
194	 * for each field, and for each field type perform a query in the form
195	 * select columnName from tableName
196	 */
197	public static void testSelectFields(Persist persist, Object obj, BeanMap beanMap, boolean useNulls) {
198		String tableName = dbName(obj.getClass().getSimpleName());
199		
200		// for each field in the bean
201		for (FieldMap fieldMap : beanMap.getFields()) {
202			String columnName = dbName(fieldMap.getFieldName());
203			String sql = "select " + columnName + " from " + tableName;
204			
205			// get field value from the bean
206			Object fieldValue = DynamicBean.getFieldValue(obj, fieldMap.getFieldName());
207			
208			// for each supported type
209			for (Class fieldType : fieldMap.getTypes()) {
210				
211				// query for a single column data using the field type (eg byte, Byte, String, InputStream, etc.)
212				Object ret = persist.read(fieldType, sql);
213				
214				if (useNulls) {
215					// check if "null", which means 0 for numeric values type as primitive (byte, short, int, etc.) 
216					if (!DynamicBean.isNull(fieldType, ret)) throw new AssertionError("Expected null value but got [" + ret 
217							+ "] as result of [" + sql + "]");
218				}
219				else {
220					if (ret==null) {
221						throw new AssertionError("Expected not null value but got null as result of [" + sql + "]");
222					}
223					
224					// TODO: maybe test compatibility of return type with field type?				
225					
226					// compare values using a method that takes into consideration "compatible" types 
227					// (eg char[]-String, double-BigDecimal, etc)
228					Object retConverted = DynamicBean.convertToType(fieldValue.getClass(), ret);
229					if (!DynamicBean.compareValues(fieldValue, retConverted)) {
230						throw new AssertionError("Expected [" + fieldValue + "] but got [" + ret + "] as result of [" + sql + "]");
231					}
232				}
233			}
234		}
235	}
236	
237	/**
238	 * perform [select * from tableName] and get the results as a map
239	 */
240	public static void testSelectMap(Persist persist, Object obj, BeanMap beanMap) {
241		String tableName = dbName(obj.getClass().getSimpleName());
242		
243		// read list of all data in the table as a map
244		String sql = "select * from " + tableName;
245		List<Map<String,Object>> mapList = persist.readMapList(sql);
246		
247		// asserts there's only one entry (added during the insert test)
248		if (mapList.size()!=1) {
249			throw new AssertionError("Expected 1 result but got [" + mapList.size() + "] as result of sql [" + sql + "]");
250		}
251		
252		// use the first (or single) map returned
253		Map m = mapList.get(0);
254		
255		// for each field in the bean
256		for (FieldMap fieldMap : beanMap.getFields()) {
257			String columnName = dbName(fieldMap.getFieldName());
258			
259			// get the field value
260			Object fieldValue = DynamicBean.getFieldValue(obj, fieldMap.getFieldName());
261			
262			// get the corresponding map value
263			Object mapValue = m.get(columnName);
264			
265			// if field supports comparisons on the map values (mysql's year2 and year4, for instance, 
266			// have Date objects here, but must be inserted as short's, therefore can't be compared properly)
267			if (fieldMap.isSupportsCompareMapValue()) {
268				
269				// compare values using a method that takes into consideration "compatible" types 
270				// (eg char[]-String, double-BigDecimal, etc) 
271				if (!DynamicBean.compareValues(fieldValue, mapValue)) {
272					throw new AssertionError("Map entry [" + columnName + "]=[" + mapValue + "] does not match field [" 
273							+ fieldMap.getFieldName() + "]=[" + fieldValue + "] as result of sql [" + sql + "]");
274				}
275			}
276		}
277	}
278	
279	/**
280	 * Tests if explicitly specifying autoGeneratedKeys in executeUpdate works
281	 */
282	public static void testExecuteUpdateAutoGeneratedKeys(Persist persist) {
283		
284		TableMapping mapping = (TableMapping) persist.getMapping(Simple.class);
285		if (mapping.supportsGetGeneratedKeys()) {
286			
287			// some data to insert
288			int intCol = DynamicBean.randomInt(0,Integer.MAX_VALUE/2);
289			String stringCol = DynamicBean.randomString(255);
290			
291			// insert with explicit auto generated keys and check result object data
292			String[] autoGeneratedKeys = new String[] { "id" };
293			Result result = persist.executeUpdate(Simple.class, "insert into simple (int_col,string_col) values(?,?)", 
294					autoGeneratedKeys, intCol, stringCol);
295			assertEquals(1, result.getGeneratedKeys().size());
296			assertEquals(1, result.getRowsModified());
297			
298			// read object and compare with inserted data
299			Simple simpleRead = persist.read(Simple.class, "select * from simple where int_col=? and string_col=?", 
300					intCol, stringCol);
301			assertNotNull(simpleRead);
302			assertEquals(intCol, simpleRead.getIntCol());
303			assertEquals(stringCol, simpleRead.getStringCol());
304			
305			// delete object and check it was removed
306			persist.delete(simpleRead);
307			simpleRead = persist.read(Simple.class, "select * from simple where int_col=? and string_col=?", intCol, stringCol);
308			assertNull(simpleRead);			
309		}
310
311	}
312	
313	/**
314	 * Tests setUpdateGeneratedKeys
315	 */
316	public static void testSetAutoGeneratedKeys(Persist persist) {
317
318		TableMapping mapping = (TableMapping) persist.getMapping(Simple.class);
319		if (mapping.supportsGetGeneratedKeys()) {
320		
321			persist.setUpdateAutoGeneratedKeys(true);
322			
323			// insert object with setUpdateAutoGeneratedKeys option
324			Simple simpleInsert = TestSimple.buildSimple();
325			simpleInsert.setId(0);
326			persist.insert(simpleInsert);
327			assertTrue(0!=simpleInsert.getId());
328			
329			// read object using primary key (auto generated)
330			Simple simpleRead = persist.read(Simple.class, "select * from simple where id=?", simpleInsert.getId());
331			assertEquals(simpleInsert, simpleRead);		
332			
333			// delete object by primary key and check it was removed
334			persist.delete(simpleRead);
335			simpleRead = persist.readByPrimaryKey(Simple.class, simpleRead.getId());
336			assertNull(simpleRead);
337			
338			persist.setUpdateAutoGeneratedKeys(false);
339			
340		}
341	}
342	
343	// ---------- helpers ----------
344	
345	/**
346	 * Returned the database table/column name related with a given bean/field name
347	 */
348	private static String dbName(String s) {
349		String name = s.replaceAll("([A-Z])", "_$1").toLowerCase();
350		return name.charAt(0)=='_' ? name.substring(1) : name;
351	}
352
353}