zoukankan      html  css  js  c++  java
  • DBUnit入门

     

    相信做过单元测试的人都会对JUnit非常的熟悉了,今天要介绍的DbUnit(http://dbunit.sourceforge.net/)则是专 门针对数据库测试的对JUnit的一个扩展,它可以将测试对象数据库置于一个测试轮回之间的状态。鉴于目前国内介绍DbUnit的系统教程比较少见,本文 将分从理论和实例两个方面带你领略DbUnit的精彩世界。

    DbUnit设计理念
    熟悉单元测试的开发人员都知道,在对数据库进行单元测试时候,通常采用的方案有运用模拟对象(mock objects)和stubs两种。通过隔离关联的数据库访问类,比如JDBC的相关操作类,来达到对数据库操作的模拟测试。然而某些特殊的系统,比如利 用了EJB的CMP(container-managed persistence)的系统,数据库的访问对象是在最底层而且很隐蔽的,那么这两种解决方案对这些系统就显得力不从心了。

    DBUnit的设计理念就是在测试之前,备份数据库,然后给对象数据库植入我们需要的准备数据,最后,在测试完毕后,读入备份数据库,回溯到测试前的状态;
    而且又因为DBUnit是对JUnit的一种扩展,开发人员可以通过创建测试用例代码,在这些测试用例的生命周期内来对数据库的操作结果进行比较。

    DbUnit测试基本概念和流程
    基于DbUnit 的测试的主要接口是IDataSet。IDataSet代表一个或多个表的数据。
    可以将数据库模式的全部内容表示为单个IDataSet 实例。这些表本身由Itable 实例来表示。
    IDataSet 的实现有很多,每一个都对应一个不同的数据源或加载机制。最常用的几种 IDataSet实现为:
    FlatXmlDataSet:数据的简单平面文件 XML 表示
    QueryDataSet:用 SQL 查询获得的数据
    DatabaseDataSet:数据库表本身内容的一种表示
    XlsDataSet :数据的excel表示

    一般而言,使用DbUnit进行单元测试的流程如下:
    1 根据业务,做好测试用的准备数据和预想结果数据,通常准备成xml格式文件。
    2 在setUp()方法里边备份数据库中的关联表。
    3 在setUp()方法里边读入准备数据。
    4 对测试类的对应测试方法进行实装:执行对象方法,把数据库的实际执行结果和预想结果进行比较。
    5 在tearDown()方法里边,把数据库还原到测试前状态。

    DbUnit开发实例
    下面通过一个实例来说明DbUnit的实际运用。

    实例准备
    比如有一个学生表[student],结构如下:


    id char(4) pk 学号
    name char(50) 姓名
    sex char(1) 性别
    birthday date 出生日期

    准备数据如下:

    id name sex birthday
    0001 翁仔 m 1979-12-31
    0002 王翠花 f 1982-08-09
    测试对象类为StudentOpe.java,里边有2个方法:
    findStudent(String id) :根据主键id找记录
    addStudent(Student student) :添加一条记录

    在测试addStudent方法时候,我们准备添加如下一条数据

    id name sex birthday
    0088 王耳朵 m 1982-01-01

    那么在执行该方法后,数据库的student表里的数据是这样的:

    id name sex birthday
    0001 翁仔 m 1979-12-31
    0002 王翠花 f 1982-08-09
    0088 王耳朵 m 1982-01-01

    然后我们说明如何对这2个方法进行单元测试。

    实例展开
    1 把准备数据和预想数据转换成xml文件
    student_pre.xml


    <?xml version='1.0' encoding="gb2312"?>
    <dataset>
    <student id="0001" name="翁仔" sex="m" birthday="1979-12-31"/>
    <student id="0002" name="王翠花" sex="f" birthday="1982-08-09"/>
    </dataset>


    student_exp.xml

    <?xml version='1.0' encoding="gb2312"?>
    <dataset>
    <student id="0001" name="翁仔" sex="m" birthday="1979-12-31"/>
    <student id="0002" name="王翠花" sex="f" birthday="1982-08-09"/>
    <student id="0088" name="王耳朵" sex="m" birthday="1982-01-01"/>
    </dataset>

    2 实装setUp方法,详细见代码注释。


    protected void setUp() {
    IDatabaseConnection connection =null;
    try{
    super.setUp();
    //本例使用postgresql数据库
    Class.forName("org.postgresql.Driver");
    //连接DB
    Connection conn=DriverManager.getConnection("jdbc:postgresql:testdb.test","postgres","postgres");
    //获得DB连接
    connection =new DatabaseConnection(conn);

    //对数据库中的操作对象表student进行备份
    QueryDataSet backupDataSet = new QueryDataSet(connection);
    backupDataSet.addTable("student");
    file=File.createTempFile("student_back",".xml");//备份文件
    FlatXmlDataSet.write(backupDataSet,new FileOutputStream(file));

    //准备数据的读入
    IDataSet dataSet = new FlatXmlDataSet( new FileInputStream("student_pre.xml"));
    DatabaseOperation.CLEAN_INSERT.execute(connection,dataSet);

    }catch(Exception e){
    e.printStackTrace();
    }finally{
    try{
    if(connection!=null) connection.close();
    }catch(SQLException e){}
    }
    }

    3 实装测试方法,详细见代码注释。

    *检索类方法,可以利用assertEquals()方法,拿表的字段进行比较。

    // findStudent
    public void testFindStudent() throws Exception{
    //执行findStudent方法
    StudentOpe studentOpe=new StudentOpe();
    Student result = studentOpe.findStudent("0001");

    //预想结果和实际结果的比较
    assertEquals("翁仔",result.getName());
    assertEquals("m",result.getSex());
    assertEquals("1979-12-31",result.getBirthDay());
    }


    *更新,添加,删除等方法,可以利用Assertion.assertEquals()方法,拿表的整体来比较。

    public void testAddStudent() throws Exception{
    //执行addStudent方法
    StudentOpe studentOpe=new StudentOpe();
    //被追加的记录
    Student newStudent = new Student("0088","王耳朵","m","1982-01-01");
    //执行追加方法
    Student result = studentOpe.addStudent(newStudent);

    //预想结果和实际结果的比较
    IDatabaseConnection connection=null;

    try{

    //预期结果取得
    IDataSet expectedDataSet = new FlatXmlDataSet(new FileInputStream("student_exp.xml"));
    ITable expectedTable = expectedDataSet.getTable("student");

    //实际结果取得
    Connection conn=getConnection();
    connection =new DatabaseConnection(conn);

    IDataSet databaseDataSet = connection.createDataSet();
    ITable actualTable = databaseDataSet.getTable("student");

    //比较
    Assertion.assertEquals(expectedTable, actualTable);

    }finally{
    if(connection!=null) connection.close();
    }
    }


    *如果在整体比较表的时候,有个别字段不需要比较,可以用DefaultColumnFilter.excludedColumnsTable()方法,
    将指定字段给排除在比较范围之外。比如上例中不需要比较birthday这个字段的话,那么可以如下代码所示进行处理:

    ITable filteredExpectedTable = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"birthday"});
    ITable filteredActualTable = DefaultColumnFilter.excludedColumnsTable(actualTable,new String[]{"birthday"});
    Assertion.assertEquals(filteredExpectedTable, filteredActualTable);


    4 在tearDown()方法里边,把数据库还原到测试前状态

    protected void tearDown() throws Exception{

    IDatabaseConnection connection =null;
    try{
    super.tearDown();
    Connection conn=getConnection();
    connection =new DatabaseConnection(conn);

    IDataSet dataSet = new FlatXmlDataSet(file);
    DatabaseOperation.CLEAN_INSERT.execute(connection,dataSet);

    }catch(Exception e){
    e.printStackTrace();
    }finally{
    try{
    if(connection!=null) connection.close();
    }catch(SQLException e){}
    }

    }


    最后
    无疑,使用DbUnit能够极大的提高数据库测试的效率,希望通过本文能够让您掌握这一数据库测试的利器
  • 相关阅读:
    SQLyog 链接数据库工具
    TortoiseSVN
    PhpStudy
    PDF
    FSCapture 图像浏览、编辑和截屏工具
    typora 浏览markdown文件
    文件传输工具
    Hadoop3 No FileSystem for scheme "hdfs"
    org.apache.hadoop.security.AccessControlException: Queue root.online already has 0 applications, cannot accept submission of application
    使用JAAS文件登陆kerberos(zookeeper)
  • 原文地址:https://www.cnblogs.com/xiaocay/p/2845415.html
Copyright © 2011-2022 走看看