1、Dao单元测试的问题

  Dao层主要工作是数据库访问,是非常重要的模块。为了保证SQL的正确执行,单元测试是必须的。但是一直以来Dao层的单元测试很难进行,主要因为几个问题

  1)单元测试必须是执行隔离的环境代码,而隔离数据库非常困难,不得不放弃这个念头。所以Dao层需要和数据库直接打交道,但是单元测试要求每次重复的动作结果都是一致,但是由于外部数据库环境的问题,测试环境无法稳定。

  2)现阶段的Dao层一般都会利用Spring的容器组装Dao对象,在辅以一些Support对象。这样的结果是没有Spring容器,无法测试Dao。

  3)每个测试之前,数据库必须处于一个稳定的已知的状态,这需要数据准备,而单元测试的数据如果要手工插入到数据库中,工作量过大。

  4)测试用例必须有断言,我们需要通过断言来判断数据是否插入数据,每个字段是否相同,这个如果没有辅助工具,而手工去一个个断言,工作量不能接受的

  2、解决方案

  为了解决以上问题,我们选择了Unitils来集成Spring、Dbunit等,完成Dao层的单元测试工作,并和Maven工程结合完成配置。

  Unitils的使用很简单,以下面的一个例子来说明。

  Dao的代码很简单,是查询、更新一个用户的账户信息

  Java代码


public class AccountDao extends JdbcDaoSupport {

    public Account getAccount(String accountId) {
        List<Account> list = null;

        list = getJdbcTemplate().query("select account_id,balance from tb_account where account_id=?",
                new Object[] { accountId }, new RowMapper<Account>() {

                    @Override
                    public Account mapRow(ResultSet rs, int rowNum) throws SQLException {
                        Account acc = new Account();
                        acc.setAccountId(rs.getString("account_id"));
                        acc.setBalance(rs.getInt("balance"));
                        return acc;
                    }
                });
        if (list.size() > 0) {
            return list.get(0);
        } else {
            return null;
        }
    }

    public int updateAccount(String accountId, int balance) {
        int ret = getJdbcTemplate().update("update tb_account set balance = ? where account_id =?",
                new Object[] { balance, accountId });
        return ret;
    }
}
 


  1)Maven的POM文件修改

  在Dao工程中的POM文件加入如下

  Java代码


  <dependency>
   <groupId>org.unitils</groupId>
   <artifactId>unitils-dbunit</artifactId>
   <version>${unitils.version}</version>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>org.unitils</groupId>
   <artifactId>unitils-spring</artifactId>
   <version>${unitils.version}</version>
   <scope>test</scope>
  </dependency>


  unitils.version目前新的为3.3版本

  2)Unitils的环境配置

  Unitils的启动,需要一个配置文件unitils.properties,这个文件默认需要放到classpath下,我们一般为test/resources/unitils.properties文件。文件内容如下

  Java代码


database.driverClassName=com.mysql.jdbc.Driver
database.url=jdbc:mysql://192.168.100.242:3306/test
database.userName=mantis
database.password=mantispw
database.schemaNames=test
database.dialect=mysql
DatabaseModule.Transactional.value.default=rollback


  database.driverClassName为测试数据库的Jdbc驱动
  database.url为测试数据库的连接串
  database.userName为测试数据库用户名
  database.schemaNames为测试数据库的schema,mysql可以不需要,Oracle必填。
  database.dialect填写为数据库类型,取值有mysql,oracle,derby等
  DatabaseModule.Transactional.value.default指的是单元测试对数据库的修改的事务策略,有rollback,disable,commit等选择,我们一般选择回滚 rollback

  3)Spring的集成

  Unitils提供了Spring的集成功能,可以在单元测试中让Spring组装我们的Dao,自动注入依赖的DataSource等。

  针对Spring集成,我们需要些前置条件

  (1)将Dao依赖的Spring配置,包括Property解析、DataSource、事务管理等主要是一些基础配置放到Maven工程的test/resources/testapplication/appContext-common.xml中。

  Java代码