Dict.CN 在線詞典, 英語學(xué)習(xí), 在線翻譯

          都市淘沙者

          荔枝FM Everyone can be host

          統(tǒng)計

          留言簿(23)

          積分與排名

          優(yōu)秀學(xué)習(xí)網(wǎng)站

          友情連接

          閱讀排行榜

          評論排行榜

          DbUnit入門實戰(zhàn)(轉(zhuǎn)載)

          相信做過單元測試的人都會對JUnit非常的熟悉了,今天要介紹的DbUnit(http://dbunit.sourceforge.net/)則是專門針對數(shù)據(jù)庫測試的對JUnit的一個擴(kuò)展,它可以將測試對象數(shù)據(jù)庫置于一個測試輪回之間的狀態(tài)。鑒于目前國內(nèi)介紹DbUnit的系統(tǒng)教程比較少見,本文將分從理論和實例兩個方面帶你領(lǐng)略DbUnit的精彩世界。
          DbUnit設(shè)計理念
          熟悉單元測試的開發(fā)人員都知道,在對數(shù)據(jù)庫進(jìn)行單元測試時候,通常采用的方案有運用模擬對象(mock objects)和stubs兩種。通過隔離關(guān)聯(lián)的數(shù)據(jù)庫訪問類,比如JDBC的相關(guān)操作類,來達(dá)到對數(shù)據(jù)庫操作的模擬測試。然而某些特殊的系統(tǒng),比如利用了EJB的CMP(container
          -managed persistence)的系統(tǒng),數(shù)據(jù)庫的訪問對象是在最底層而且很隱蔽的,那么這兩種解決方案對這些系統(tǒng)就顯得力不從心了。
          DBUnit的設(shè)計理念就是在測試之前,備份數(shù)據(jù)庫,然后給對象數(shù)據(jù)庫植入我們需要的準(zhǔn)備數(shù)據(jù),最后,在測試完畢后,讀入備份數(shù)據(jù)庫,回溯到測試前的狀態(tài);
          而且又因為DBUnit是對JUnit的一種擴(kuò)展,開發(fā)人員可以通過創(chuàng)建測試用例代碼,在這些測試用例的生命周期內(nèi)來對數(shù)據(jù)庫的操作結(jié)果進(jìn)行比較。
          DbUnit測試基本概念和流程
          基于DbUnit 的測試的主要接口是IDataSet。IDataSet代表一個或多個表的數(shù)據(jù)。
          可以將數(shù)據(jù)庫模式的全部內(nèi)容表示為單個IDataSet 實例。這些表本身由Itable 實例來表示。
          IDataSet 的實現(xiàn)有很多,每一個都對應(yīng)一個不同的數(shù)據(jù)源或加載機(jī)制。最常用的幾種 IDataSet實現(xiàn)為:
          FlatXmlDataSet:數(shù)據(jù)的簡單平面文件 XML 表示
          QueryDataSet:用 SQL 查詢獲得的數(shù)據(jù)
          DatabaseDataSet:數(shù)據(jù)庫表本身內(nèi)容的一種表示
          XlsDataSet :數(shù)據(jù)的excel表示
          一般而言,使用DbUnit進(jìn)行單元測試的流程如下:
          1 根據(jù)業(yè)務(wù),做好測試用的準(zhǔn)備數(shù)據(jù)和預(yù)想結(jié)果數(shù)據(jù),通常準(zhǔn)備成xml格式文件。
          2 在setUp()方法里邊備份數(shù)據(jù)庫中的關(guān)聯(lián)表。
          3 在setUp()方法里邊讀入準(zhǔn)備數(shù)據(jù)。
          4 對測試類的對應(yīng)測試方法進(jìn)行實裝:執(zhí)行對象方法,把數(shù)據(jù)庫的實際執(zhí)行結(jié)果和預(yù)想結(jié)果進(jìn)行比較。
          5 在tearDown()方法里邊,把數(shù)據(jù)庫還原到測試前狀態(tài)。
          DbUnit開發(fā)實例
          下面通過一個實例來說明DbUnit的實際運用。
          實例準(zhǔn)備
          比如有一個學(xué)生表[student],結(jié)構(gòu)如下:

          --------------------------------------------------------------------------------
          id 
          char(4) pk 學(xué)號
          name 
          char(50) 姓名
          sex 
          char(1) 性別
          birthday date 出生日期
          --------------------------------------------------------------------------------
          準(zhǔn)備數(shù)據(jù)如下:
          --------------------------------------------------------------------------------
          id name sex birthday
          0001 翁仔 m 1979-12-31
          0002 王翠花 f 1982-08-09
          --------------------------------------------------------------------------------
          測試對象類為StudentOpe.java,里邊有2個方法:
          findStudent(String id) :根據(jù)主鍵id找記錄
          addStudent(Student student) :添加一條記錄
          在測試addStudent方法時候,我們準(zhǔn)備添加如下一條數(shù)據(jù)
          --------------------------------------------------------------------------------
          id name sex birthday
          0088 王耳朵 m 1982-01-01
          --------------------------------------------------------------------------------
          那么在執(zhí)行該方法后,數(shù)據(jù)庫的student表里的數(shù)據(jù)是這樣的:
          --------------------------------------------------------------------------------
          id name sex birthday
          0001 翁仔 m 1979-12-31
          0002 王翠花 f 1982-08-09
          0088 王耳朵 m 1982-01-01
          --------------------------------------------------------------------------------
          然后我們說明如何對這2個方法進(jìn)行單元測試。
          實例展開
          1 把準(zhǔn)備數(shù)據(jù)和預(yù)想數(shù)據(jù)轉(zhuǎn)換成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方法,詳細(xì)見代碼注釋。

          --------------------------------------------------------------------------------
          protected void setUp() {
          IDatabaseConnection connection 
          =null;
          try{
          super.setUp();
          //本例使用postgresql數(shù)據(jù)庫
          Class.forName("org.postgresql.Driver");
          //連接DB
          Connection conn=DriverManager.getConnection("jdbc:postgresql:testdb.test","postgres","postgres");
          //獲得DB連接
          connection =new DatabaseConnection(conn);
          //對數(shù)據(jù)庫中的操作對象表student進(jìn)行備份
          QueryDataSet backupDataSet = new QueryDataSet(connection);
          backupDataSet.addTable(
          "student");
          file
          =File.createTempFile("student_back",".xml");//備份文件
          FlatXmlDataSet.write(backupDataSet,new FileOutputStream(file));
          //準(zhǔn)備數(shù)據(jù)的讀入
          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 實裝測試方法,詳細(xì)見代碼注釋。
          *檢索類方法,可以利用assertEquals()方法,拿表的字段進(jìn)行比較。
          --------------------------------------------------------------------------------
          // findStudent
          public void testFindStudent() throws Exception{
          //執(zhí)行findStudent方法
          StudentOpe studentOpe=new StudentOpe();
          Student result 
          = studentOpe.findStudent("0001");
          //預(yù)想結(jié)果和實際結(jié)果的比較
          assertEquals("翁仔",result.getName());
          assertEquals(
          "m",result.getSex());
          assertEquals(
          "1979-12-31",result.getBirthDay());
          }
          --------------------------------------------------------------------------------
          *更新,添加,刪除等方法,可以利用Assertion.assertEquals()方法,拿表的整體來比較。
          --------------------------------------------------------------------------------
          public void testAddStudent() throws Exception{
          //執(zhí)行addStudent方法
          StudentOpe studentOpe=new StudentOpe();
          //被追加的記錄
          Student newStudent = new Student("0088","王耳朵","m","1982-01-01");
          //執(zhí)行追加方法
          Student result = studentOpe.addStudent(newStudent);
          //預(yù)想結(jié)果和實際結(jié)果的比較
          IDatabaseConnection connection=null;
          try{
          //預(yù)期結(jié)果取得
          IDataSet expectedDataSet = new FlatXmlDataSet(new FileInputStream("student_exp.xml"));
          ITable expectedTable 
          = expectedDataSet.getTable("student");
          //實際結(jié)果取得
          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這個字段的話,那么可以如下代碼所示進(jìn)行處理:
          --------------------------------------------------------------------------------
          ITable filteredExpectedTable 
          = DefaultColumnFilter.excludedColumnsTable(expectedTable, new String[]{"birthday"});
          ITable filteredActualTable 
          = DefaultColumnFilter.excludedColumnsTable(actualTable,new String[]{"birthday"});
          Assertion.assertEquals(filteredExpectedTable, filteredActualTable);
          --------------------------------------------------------------------------------
          4 在tearDown()方法里邊,把數(shù)據(jù)庫還原到測試前狀態(tài)
          --------------------------------------------------------------------------------
          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){}
          }
          }

          posted on 2010-10-09 14:20 都市淘沙者 閱讀(320) 評論(0)  編輯  收藏 所屬分類: Hibernate/ORM

          主站蜘蛛池模板: 芮城县| 灵宝市| 洛浦县| 彰化市| 逊克县| 广南县| 阿拉善左旗| 肇东市| 霍林郭勒市| 阜康市| 商城县| 昌乐县| 新沂市| 蕲春县| 旬阳县| 辽阳市| 濉溪县| 绵竹市| 拜泉县| 和静县| 崇仁县| 会同县| 雷波县| 房产| 贵德县| 浪卡子县| 凤凰县| 邓州市| 浦城县| 崇明县| 罗甸县| 凤庆县| 长汀县| 色达县| 穆棱市| 双柏县| 石柱| 淮阳县| 那坡县| 阿尔山市| 新丰县|