龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > JAVA开发 >

设计自己的DbUnit

时间:2009-12-23 15:42来源:未知 作者:admin 点击:
分享到:
在数据库代码测试中,一般情况使用2种方案: 一是使用mock objects; 二是使用DbUnit。 mock objects基于物理隔离层的概念,将涉及到数据库操作的代码,全用虚拟对象代替。这种方案,对业

  在数据库代码测试中,一般情况使用2种方案:
  一是使用mock objects;
  二是使用DbUnit。
  
  mock objects基于物理隔离层的概念,将涉及到数据库操作的代码,全用虚拟对象代替。这种方案,对业务领域里的代码来讲是可行的,也比较方便,但对于数据库操作层,此方案无用武之地,因为我们必须实实在在地与数据库打交道。
  
  而在数据库测试中,因为我们力求将每个TestCase中众多的测试方法完全隔离起来,不会因为一个测试方法因测试增加、删除功能而影响到另一个测试方法,这样,在每一个测试之前,数据库的状态是否稳定,甚至是完全不变,就显得很重要了。而这点,正是数据库测试的难点。
  
  Dbunit解决了这个问题。其原理很简单,就是在每个测试方法之前后,通过增删一些固定的记录,保持了数据库的固定状态,由此,我们可以在每个测试方法中自由地增删记录,而不用担心会影响到别的测试方法。
  
  但Dbunit也有一个问题,即它不能删除非空的外键记录。举例来说,假设“员工”表中有一非空字段为“部门编号”,引用了“部门”表的id, 只要“员工”表存在任一记录,“部门”表将不能被删除,强行删除将出现违犯约束(constraint violation)的异常。当然,假如必要,我们可以将数据库的约束条件改为连锁删除,这样,一旦我们删除一名员工记录,其所在的部门记录也将从“部门”表中删除。而此又会导致“员工”表中所有该部门的员工全被删除。这是绝对不答应的。当然,作为测试,我们可以先删除“员工”表,再删除“部门”表。
  
  但有时,某些表自己引用自己,如“组织”表中有一“上级组织编号”字段,是自己“组织编号”的外键,即,此字段引用了本表中其他记录的“组织编号”。此时,我们必须先将这些引用了其他记录的“组织编号”的记录先删除,才能删除此表中的其他记录。而Dbunit在实现上,只是用了一个简单的"delete from ..."的SQL语句,不能解决这个问题。
  
  Dbunit的原理是如此简单,我们完全可以设计的“Dbunit”,通过多重循环语句,干脆利落地删除自引用的整表。我们的“Dbunit”,可以命名为“SqlRunner”。

  package com.sarkuya.util.database;
  
  import Java.sql.Connection;
  import java.sql.DriverManager;
  import java.sql.ResultSet;
  import java.sql.SQLException;
  import java.sql.Statement;
  
  public class SqlRunner {
      
      static {
          try {
              Class.forName("org.hsqldb.jdbcDriver");
          } catch (ClassNotFoundException ex) {
              ex.printStackTrace();
          }
      }
  
      public static void executeUpdate(String sql) {
          Connection conn;
          Statement stmt;
          
          try {
              conn = DriverManager.getConnection("jdbc:hsqldb:mem:testingdb", "sa", "");
              stmt = conn.createStatement();
              
              stmt.executeUpdate(sql);
              
              stmt.close();
              conn.close();
          } catch (SQLException ex) {
              ex.printStackTrace();
          }
          
      }
      
      public static boolean isUndeletableForSelfReference (String 表名, String 字段名) {
          Connection conn;
          Statement stmt;
          boolean result = true;
          
          try {
              conn = DriverManager.getConnection("jdbc:hsqldb:mem:testingdb", "sa", "");
              stmt = conn.createStatement();
              
              ResultSet rs = stmt.executeQuery("select count(*) from " + 表名 + " where " + 字段名 + " is not null");
              
              rs.next();
              
              if (rs.getInt(1) != 0) {
                  result = true;
              }
              else {
                  result = false;
              }
  
              rs.close();
              stmt.close();
              conn.close();
          } catch (SQLException ex) {
              ex.printStackTrace();
          }
          
          return result;
      }

  
  

精彩图集

赞助商链接