边城愚人

如果我不在边城,我一定是在前往边城的路上。

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  31 随笔 :: 0 文章 :: 96 评论 :: 0 Trackbacks

        在做 Java 企业程序的时候,不可避免地要和外部资源打交道,比如数据库, Http 请求等。对于这些外部资源的处理,我们可采取的操作或者是直接处理或者是模拟处理。当我们使用 Webwork Spring Hibernate 等框架时,我们要测试的并不仅仅是 Java 代码,我们还要测试依赖于这些框架的配置文件等等。因此,对于数据持久化的测试, Mock 方法是行不通的,我们需要真实地测试数据库操作。对于持久化测试来说,重要的是创造出已知的“干净的”的准备数据。如果我们在测试一个持久化方法前不能确定数据库到底存着什么数据,我们只能通过反复地查看数据库数据来验证测试方法的正确性了(这就是我和大多数人以前使用的最“直接”的方法)。现在就让我们使用 DbUnit ,来更好的更自动化的测试持久化操作吧!

        先介绍一下 DbUnit DbUnit 是一个 JUnit 扩展,适用于数据驱动的程序。使用 DbUnit ,可以在测试运行期间将数据库的数据处于已知状态,这样在测试时可以方便地写出测试断言,也能自动地完成对数据持久化方法的测试。在使用上, DbUnit 也很简单, 它提供了大量的类对与数据库相关的操作进行了抽象和封装,大多数情况下你只需要使用少量简单的 API

        下面我通过一个实际的小例子,介绍一下如何使用 DbUnit 。我也是刚刚使用上了 DbUnit ,经验上不是很丰富,如果文中有不对的地方,也欢迎指正。这个例子很简单,我将较为详细地说明如何使用 Hibernate DbUnit 进行测试。

        测试第一步,准备数据集。操作的数据表就是如下的 Account 表(使用的数据库为Mysql):


create   table  Account(
    id 
bigint   not   null  auto_increment,
    name 
varchar ( 50 not   null ,
    
primary   key (id)
)
character   set  gbk;

        至于 Account 类,映射文件等这里就不给出了。AccountDAO 接口很简单,只有两个方法:

public   interface  AccountDAO {
    
void  insert(Account a);
    List
< Account >  findAll();
}

   

        实现类如下:

public   class  AccountHibernateDAO  implements  AccountDAO{
    
    
public   void  insert(Account a){
        Session s 
=  HibernateSessionFactory.getSession();
        s.save(a);
        s.close();
    }
    
    
public  List < Account >  findAll(){
        Session s 
=   HibernateSessionFactory.getSession();
        List
< Account >  l  =  (List < Account > )s.createCriteria(Account. class ).list();
        s.close();
        
return  l;
    }
}

        在测试前,要准备出数据表中要装入的数据(也就是数据集),这里给出与Account表对应的数据集文件 Accout.xml 内容如下:


<? xml version='1.0' encoding='UTF-8' ?>
< dataset >
    
< Account  id ="1"  name ="kafka" />
    
< Account  id ="2"  name ="0102" />
</ dataset >

    

        数据集就是一个 xml 文件, <dataset> 中的每个节点对应的就是一条表数据记录(一个 dataset文件可以对应多个数据表记录 )。这里的 <Account> 节点对应的就是 Account 表,属性就是表中的字段,属性值就是字段值了。在做测试时,数据集中的内容可以手动敲进去,也可以通过工具将数据库中的数据导出来。 对于数据集的详细信息,可参考 http://dbunit.sourceforge.net/components.html#FlatXmlDataSet
    

    测试第二步,扩展 DBTestCase DBTestCase 是继承自 JUnit 的类,扩展它需要实现 getDataSet() 来提供数据集。 另外,你也可以根据需要扩展继承于 DBTestCase 的子类 JdbcBasedDBTestCase DataSourceBasedDBTestCas JndiBasedDBTestCase 。下面是继承于 DBTestCase AccountHibernateDAO 的测试类 AccountHibernateDAOTest

package  hibernatesample.dao.impl;
import  hibernatesample.domain.Account;
import  hibernatesample.util.HibernateSessionFactory;
import  java.io.File;
import  java.io.InputStream;
import  java.util.List;
import  org.dbunit.Assertion;
import  org.dbunit.DBTestCase;
import  org.dbunit.PropertiesBasedJdbcDatabaseTester;
import  org.dbunit.dataset.IDataSet;
import  org.dbunit.dataset.ITable;
import  org.dbunit.dataset.xml.FlatXmlDataSet;
import  org.dbunit.operation.DatabaseOperation;

public   class  AccountHibernateDAOTest  extends  DBTestCase {

    
private  AccountHibernateDAO accountDAO;
    
    
public  AccountHibernateDAOTest(){
        System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, HibernateSessionFactory.getDriverClass());
   System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, HibernateSessionFactory.getConnectionURL());
   System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME,HibernateSessionFactory.getUsername());
   System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD,HibernateSessionFactory.getPassword());
    }
    
    @Override
    
protected  IDataSet getDataSet()  throws  Exception {
        String path 
=   " hibernatesample " + File.separator + " dao " + File.separator + " dataset " + File.separator + " Account.xml " ;
        InputStream in 
=   this .getClass().getClassLoader().getResourceAsStream(path);
        
return   new  FlatXmlDataSet(in);
    }

    
    @Override
    
protected  DatabaseOperation getSetUpOperation()  throws  Exception {
        
return  DatabaseOperation.CLEAN_INSERT;
    }

    @Override
    
protected  DatabaseOperation getTearDownOperation()  throws  Exception {
        
return  DatabaseOperation.NONE;
    }

    
protected   void  setUp()  throws  Exception {
        
super .setUp();
        accountDAO 
=   new  AccountHibernateDAO();
    }

    
public   void  testInsert() {
        Account a 
=   new  Account();
        a.setName(
" aa " );
        accountDAO.insert(a);
        List
< Account >  l  =  accountDAO.findAll();
        assertEquals(
3 , l.size());
        Account b 
=  l.get( 2 );
        assertEquals(
" aa " , b.getName());
    }

    
public   void  testFindAll() {
        List
< Account >  l  =  accountDAO.findAll();
        assertEquals(
2 , l.size());
        Account a 
=  l.get( 0 );
        assertEquals(
new  Long( 1 ), a.getId());
        assertEquals(
" kafka " , a.getName());
        Account b 
=  l.get( 1 );
        assertEquals(
new  Long( 2 ), b.getId());
        assertEquals(
" 0102 " , b.getName());
    }

    
public   void  testDataset()  throws  Exception {
        IDataSet databaseDataSet 
=  getConnection().createDataSet();
        ITable actualTable 
=  databaseDataSet.getTable( " Account " );
        IDataSet expectedDataSet 
=  getDataSet();
        ITable expectedTable 
=  expectedDataSet.getTable( " Account " );
        Assertion.assertEquals(expectedTable, actualTable);
    }
}

        上面的DBTestCase 依赖于 IDatabaseTester 接口完成工作,而 PropertiesBasedJdbcDatabaseTester 就是其使用的默认实现, AccountHibernateDAOTest 构造函数的作用是完成数据库连接参数的设置。 protected IDataSet getDataSet() 实现了装载数据集到 IDataSet 中。 getSetUpOperation getTearDownOperation 是可选的方法,返回的 DatabaseOperation DBTestCase SetUp TearDown 中将执行的操作, getSetUpOperation 默认的操作为 DatabaseOperation.CLEAN_INSERT ,也就是先清空数据表中的数据再插入数据集中的数据到数据表中。getTearDownOperation 默认的操作为 DatabaseOperation.NONE ,就是什么也不处理。可选的操作还有几个,可参考文档进行设置,但默认的设置是最通用的了。 testDataset ()只是测试数据集中的数据和装载到数据库中数据是否一致。

       通过上面的设置,我们就可以测试dao方法的正确性了,而我们要做的只是准备dataset文件及使用少量的DbUnit API(可以将这些操作写到一个抽象类中,测试类都继承自这个抽象类)。下一篇将介绍整合SpringHibernateDbUnit进行测试。

posted on 2007-06-14 09:03 kafka0102 阅读(2755) 评论(2)  编辑  收藏 所属分类: TDD

评论

# re: 使用DbUnit进行持久化测试(1) 2007-06-14 09:19 kafka0102
有谁知道如何在文章中附上文件?  回复  更多评论
  

# re: 使用DbUnit进行持久化测试(1) 2007-07-09 16:10 iamzzb
@kafka0102
在word中,选择'插入'-'工具'-'对象'-'由文件创建'-'浏览'找到要出入的文件-'
显示为图标'-'确定'应该是你要的效果吧  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航: