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能够极大的提高数据库测试的效率,希望通过本文能够让您掌握这一数据库测试的利器
    (转自:http://www.blogjava.net/liuzheng/articles/190128.html)

  • 相关阅读:
    Codeforces 1485C Floor and Mod (枚举)
    CodeForces 1195D Submarine in the Rybinsk Sea (算贡献)
    CodeForces 1195C Basketball Exercise (线性DP)
    2021年初寒假训练第24场 B. 庆功会(搜索)
    任务分配(dp)
    开发工具的异常现象
    Telink MESH SDK 如何使用PWM
    Telink BLE MESH PWM波的小结
    [LeetCode] 1586. Binary Search Tree Iterator II
    [LeetCode] 1288. Remove Covered Intervals
  • 原文地址:https://www.cnblogs.com/ericsun/p/2263062.html
Copyright © 2011-2022 走看看