HSQL 内存数据库在unit test 中的使用

bluetears 2012-01-10

如果我们项目采用 Hibernate  访问DB2/Oracle 的应用需要做unit test。 应该怎么做呢?

一种  是 连真实的db2 的数据库, 每一个需要数据库访问的  unit  test 放到 transaction 中 , 在unit test After 方法中  rollback  所做的 transaction,  保证数据库clean。

另外一种是连H2  或者 HSql 之类的内存数据库,  每一个unit test 都是干净的数据库。  这两种方法应该将各有利弊,  采用相同类型的数据库, 如果 unit test 失败 或者 unit test 之间可能会造成 干扰,  而内存数据库呢毕竟是不同类型。 涉及到DAO 中要采用 特定数据库的特性就不行了。   比如现有项目是访问 DB2数据库, 在插入或者修改业务数据表时 会通过触发器 在业务表的audit 表中增加audit 数据。  这个用内存数据库就得不到相同的结果。  

各有利弊也得选啊,  客户选择了用HSQL 来做 db unit test。  跟 HSQL 做 unit test 的最佳拍档 是 dbunit。  我们可以准备好  DDL 来创建表结构。 数据呢, 通过把DB2中的 数据导出到 xml 中  ,  dbunit 可以将一个xml 文件看成一个dataset。   这点跟 dotNet 中的 ADO.NET 比较相似, 一个dataset 中 也可以指定多个表的数据。但是这有个缺点, 如果数据量大了, 性能就很差, 原因当然是xml document 的解析效率太差。 我现在是采用了自己生成insert sql 语句。 然后利用 HSql 的 org.hsqldb.cmdline.SqlFile  可以很方便的执行一个sql 文件。 采用这种方式, 基本上可以将测试数据库里面的所有测试数据倒出来 几千 上万条数据, 100 多张表 也就 10几秒钟 搞定到内存。

在使用hsql jar 包的时候碰到一个问题, 主键用 identity 类型 的时候 只有 1.8 版本的 不支持 Hibernate  的 getGeneratedkey, 会抛出一个错误, 换成 2.2.6 之后 OK。

目前做了两个 utiltiy 类 : 一个是生成表的 ddl,  一个是 生成 指定表的 insert sql。 ddl 可以所有表都放到一个文件, 而数据可以做成 一张表一个文件, 并且在具体的test 之间有开发人员之间加。  ddl 则放到 test 基类每次加载。 

相关推荐