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