qiyadeng

          專注于Java示例及教程
          posts - 84, comments - 152, trackbacks - 0, articles - 34

          讓DbUnit加入你的單元測(cè)試

          Posted on 2007-06-25 11:45 qiyadeng 閱讀(1985) 評(píng)論(0)  編輯  收藏
           

          開(kāi)始

          1.    DBTestCase的子類建立數(shù)據(jù)庫(kù)

          2.    用你自己的TestCase子類建立數(shù)據(jù)庫(kù)

          3.    數(shù)據(jù)庫(kù)數(shù)據(jù)校驗(yàn)

          4.    DbUnitAnt任務(wù)和Canoo web測(cè)試(此處省略,另詳)

           

          DBTestCase的子類建立數(shù)據(jù)庫(kù)

           

          第一步:創(chuàng)建你的dataset文件

          你的測(cè)試需要一些數(shù)據(jù)。這就意味著你必須創(chuàng)建dataset。許多情況下你都是處理xmldataset。你可以人工湊一些一般的xml dataset或是從你的數(shù)據(jù)庫(kù)中導(dǎo)出一個(gè)xml dataset.

           

          第二步:繼承DBTestCase

          現(xiàn)在你要?jiǎng)?chuàng)建一個(gè)測(cè)試類。最簡(jiǎn)單的方式是用通過(guò)繼承DbUnitDBTestCase來(lái)創(chuàng)建你自己的測(cè)試類。DBTestCase繼承了JunitTestCase類。一個(gè)模板方法你需要實(shí)現(xiàn),getDataSet()返回你在第一步創(chuàng)建的datasetDBTestCase依靠IdatabaseTester來(lái)工作,默認(rèn)的配置是使用PropertiesBaseJdbcDatabaseTester,它是用系統(tǒng)屬性來(lái)指出DriverManager的配置。最簡(jiǎn)單的方式是在你測(cè)試類的構(gòu)造函數(shù)中配置它。你可以通過(guò)覆蓋getDatabaseTester()方法來(lái)修改它的行為。

           

          使用下面提供的三種IDatabaseTester之一實(shí)現(xiàn),你也可以使用下面表中描述的DBTestCase的其它子類。

          JdbcBaseDBTestCase

          使用DriverManager來(lái)創(chuàng)建連接(JdbcDatabaseTester的幫助下)

          DataSourceBasedDBTestCase

          使用javax.sql.DataSource來(lái)創(chuàng)建連接(DataSourceDatabaseTester的幫助下)

          JndiBasedDBTestCase

          使用javax.sql.DataSourece通過(guò)JNDI定位(jndiDatabaseTester的幫助下)

           

          下面是一個(gè)簡(jiǎn)單的實(shí)現(xiàn),連接到一個(gè)Hypersonic數(shù)據(jù)庫(kù)并返回xml dataset

           

          public class SampleTest extends DBTestCase

          {

              
          public SampleTest(String name)

              {

                  
          super( name );

                  System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, 
          "org.hsqldb.jdbcDriver" );

                  System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, 
          "jdbc:hsqldb:sample" );

                  System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, 
          "sa" );

                  System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, 
          "" );

              
          // System.setProperty( PropertiesBasedJdbcDatabaseTester.DBUNIT_SCHEMA, "" );

              }

           

              
          protected IDataSet getDataSet() throws Exception

              {

                  
          return new FlatXmlDataSet(new FileInputStream("dataset.xml"));

              }

          }

           

          第三步:(可選)實(shí)現(xiàn)getSetUpOperation()getTearDownOperation()方法

          默認(rèn)的情況,DbUnit在每次執(zhí)行test之前執(zhí)行一個(gè)CLEAN_INSERT操作并且不之后不執(zhí)行清除操作。你可以通過(guò)覆蓋getSetUpOperation()getTearDownOperation()來(lái)改變這個(gè)行為。

           

          下面這個(gè)例子演示你可以通過(guò)簡(jiǎn)單的覆蓋方法改變執(zhí)行測(cè)試前和后。

           

          public class SampleTest extends DBTestCase

          {

              

              
          protected DatabaseOperation getSetUpOperation() throws Exception

              {

                  
          return DatabaseOperation.REFRESH;

              }

           

              
          protected DatabaseOperation getTearDownOperation() throws Exception

              {

                  
          return DatabaseOperation.NONE;

              }

              

          }

           

          第四步:實(shí)現(xiàn)你的testXXX()方法

          就像你使用JUit一樣實(shí)現(xiàn)test方法。你的數(shù)據(jù)庫(kù)在測(cè)試方法之前初始化并且在測(cè)試之后清除,這取決于你在前幾步是怎么做的。

           

           

           

          用你自己的TestCase子類建立數(shù)據(jù)庫(kù)

          為了使用DbUnit你不是必須要繼承DBTestCase類。你可以覆蓋標(biāo)準(zhǔn)的JunitSetUp()方法,執(zhí)行你所需要的數(shù)據(jù)庫(kù)操作。如果你要執(zhí)行清除,同樣覆蓋teardown()方法。

           

          例如:

           

          public class SampleTest extends TestCase

          {

              
          public SampleTest(String name)

              {

                  
          super(name);

              }

           

              
          protected void setUp() throws Exception

              {

                  
          super.setUp();

           

                  
          // initialize your database connection here

                  IDatabaseConnection connection 
          = null;

                  
          // 

           

                  
          // initialize your dataset here

                  IDataSet dataSet 
          = null;

                  
          // 

           

                  try1

                  {

                      DatabaseOperation.CLEAN_INSERT.execute(connection, dataSet);

                  }

                  
          finally

                  {

                      connection.close();

                  }

              }

              

          }

           

           

          自從2.2版本你可以使用IdatabaseTester來(lái)完成同樣的功能。就像前面所提到過(guò)的,DBTestCase內(nèi)部是使用IdatabaseTester來(lái)實(shí)現(xiàn)的。你的測(cè)試類可以使用這個(gè)功能操作數(shù)據(jù)集(DataSets)。目前有4個(gè)方便的實(shí)現(xiàn)。

          JdbcDatabaseTester

          使用DriverManager來(lái)創(chuàng)建連接。

          PropertiesBasedJdbcDatabaseTester

          也是使用DriverManager來(lái)創(chuàng)建連接,但是配置信息是從系統(tǒng)屬性中讀取的。這是DBTestCase的默認(rèn)實(shí)現(xiàn)方式。

          DataSourceDatabaseTester

          使用javax.sql.DataSource創(chuàng)建連接。

          JndiDatabaseTester

          使用javax.sql.DataSource通過(guò)JNDI尋找

           

           

          你也可以提供你自己的IdatabaseTester實(shí)現(xiàn),推薦使用AbstractDatabaseTester作為一個(gè)開(kāi)始點(diǎn)。

          例:

           

          public class SampleTest extends TestCase

          {

              
          private IDatabaseTester databaseTester;

           

              
          public SampleTest(String name)

              {

                  
          super(name);

              }

           

              
          protected void setUp() throws Exception

              {

                  databaseTester 
          = new JdbcDatabaseTester("org.hsqldb.jdbcDriver",

                      
          "jdbc:hsqldb:sample""sa""");

           

                  
          // initialize your dataset here

                  IDataSet dataSet 
          = null;

                  
          // 

           

                  databaseTester.setDataSet( dataSet );

              
          // will call default setUpOperation

                  databaseTester.onSetUp();

              }

           

              
          protected void tearDown() throws Exception

              {

              
          // will call default tearDownOperation

                  databaseTester.onTearDown();

              }

              

          }

           

           

           

          數(shù)據(jù)庫(kù)數(shù)據(jù)校驗(yàn)

          DbUnit提供校驗(yàn)兩個(gè)表或是數(shù)據(jù)集是否包含相同的數(shù)據(jù)的方法。下面的兩個(gè)方法是在執(zhí)行測(cè)試類的時(shí)候可以校驗(yàn)?zāi)愕臄?shù)據(jù)庫(kù)中是否包含預(yù)期的數(shù)據(jù)。

           

           

          public class Assertion

          {

              
          public static void assertEquals(ITable expected, ITable actual)

              
          public static void assertEquals(IDataSet expected, IDataSet actual)

          }

           

          例子

          以下例子,展示怎么比較一個(gè)數(shù)據(jù)庫(kù)表的快照和一個(gè)XML表。

           

          public class SampleTest extends DBTestCase

          {

              
          public SampleTest(String name)

              {

                  
          super(name);

              }

           

              
          // Implements required setup methods here

              

           

              
          public void testMe() throws Exception

              {

                  
          // Execute the tested code that modify the database here

                  

           

           

                  
          // Fetch database data after executing your code

                  IDataSet databaseDataSet 
          = getConnection().createDataSet();

                  ITable actualTable 
          = databaseDataSet.getTable("TABLE_NAME");

           

                  
          // Load expected data from an XML dataset

                  IDataSet expectedDataSet 
          = new FlatXmlDataSet(new File("expectedDataSet.xml"));

                  ITable expectedTable 
          = expectedDataSet.getTable("TABLE_NAME");

           

                  
          // Assert actual database table match expected table

                  Assertion.assertEquals(expectedTable, actualTable);

              }

          }

           

          actual數(shù)據(jù)集是一個(gè)數(shù)據(jù)庫(kù)的快照可以和你想要比較的expected數(shù)據(jù)集進(jìn)行比較。就象他的名字一樣,expected數(shù)據(jù)集中包含預(yù)期的值。

           

          expected數(shù)據(jù)集一定要和你建立數(shù)據(jù)庫(kù)時(shí)的對(duì)象不一樣。因?yàn)槟阈枰獌蓚€(gè)數(shù)據(jù)集,一個(gè)是在測(cè)試之前建立數(shù)據(jù)庫(kù),一個(gè)是提供匹配測(cè)試時(shí)的expected數(shù)據(jù)。

           

           

          使用查詢來(lái)獲取數(shù)據(jù)庫(kù)的快照

          你也可以校驗(yàn)查詢的結(jié)果是不是和期望的數(shù)據(jù)集匹配。這個(gè)查詢可以使查詢一個(gè)表中的一部分也可以是多表的聯(lián)合查詢。

           

          Itable actualJoinData = getConnection().createQueryTable("RESULT_NAME",

                          
          "SELECT * FROM TABLE1, TABLE2 WHERE ");

           

           

          在比較的時(shí)候忽略一些列

           有些時(shí)候希望忽視一些列來(lái)進(jìn)行比較,特別是對(duì)主鍵,日期或是時(shí)間列,這些列的值是在測(cè)試的時(shí)候又代碼產(chǎn)生的。一種方式是在你的expected表中省略你不想比較的列的聲明。這樣你可以過(guò)濾真實(shí)的數(shù)據(jù)庫(kù)表只暴露出expected表中的列。

           

           下面這些代碼片段向你展示怎么過(guò)濾真實(shí)數(shù)據(jù)庫(kù)中的表。首先,真實(shí)數(shù)據(jù)庫(kù)中必須包含expected表中的所有列。另外,真實(shí)表中有這些列而expected表中沒(méi)有這些列,這種情況是允許的。

           

           

              ITable filteredTable = DefaultColumnFilter.includedColumnsTable(actual, 

                      expected.getTableMetaData().getColumns());

              Assertion.assertEquals(expected, filteredTable);

           

           

          這個(gè)技術(shù)的主要限制是你不能在你的expected數(shù)據(jù)集XML中使用DTD。使用DTD的話你需要過(guò)濾expected表和真實(shí)表中的列。查看FAQ中關(guān)于在運(yùn)行時(shí)排除一些表的列(excluding some table columns at runtime)

           

          行順序

          默認(rèn)的情況下,用DbUnit得到的數(shù)據(jù)庫(kù)快照表是按主鍵排序的。如果一個(gè)表沒(méi)有主鍵或是主鍵是由數(shù)據(jù)庫(kù)自動(dòng)產(chǎn)生的,行的順序是不確定的,那么assertEquals將會(huì)失敗。

           你一定要排序你的數(shù)據(jù)庫(kù)快照通過(guò)在IdatabaseConnection.createQueryTable時(shí)手工加入”ORDER BY”語(yǔ)句。或者你可以這樣使用SortedTable:

           

          Assertion.assertEquals(new SortedTable(expected),

                          
          new SortedTable(actual, expected.getTableMetaData()));

           

            


          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 博乐市| 新营市| 巫溪县| 呼和浩特市| 镇巴县| 饶平县| 嘉峪关市| 泰安市| 武乡县| 大化| 高碑店市| 万年县| 安多县| 天峻县| 旺苍县| 黄陵县| 兴文县| 阆中市| 潮州市| 福鼎市| 扬州市| 沿河| 凤庆县| 成武县| 巨野县| 同心县| 雷州市| 崇文区| 钟山县| 祁阳县| 凤山市| 桂东县| 澄城县| 松原市| 左贡县| 延边| 溧阳市| 肥城市| 东莞市| 万宁市| 文山县|