Java单元测试Junit(二)使用DBUnit扩展JUnit

在我们使用JUnit单元测试框架编写单元测试的时候,少不免要对数据库进行操作,但请试想一下,当我要编写一个获取用户的单元测试时,数据库是不存在该记录的,那么我要测试获取用户时就需要往数据库添加一条用户记录,但当获取用户的单元测试完成并成功后,此测试并没有清理现场(删除插入数据库的记录),那样当我们再有单元测试需要插入记录时,就会造成ID冲突的情况,少量的单元测试还可以避免此种情况,但当单元测试的数据庞大时,就会出现各种各样的问题,而DBUnit可以帮助我们解决这类型的问题

 
 
  1. <dependency> 
  2.     <groupId>org.dbunit</groupId> 
  3.     <artifactId>dbunit</artifactId> 
  4.     <version>2.4.9</version> 
  5.     <scope>test</scope> 
  6. </dependency> 
  7. <dependency> 
  8.     <groupId>org.slf4j</groupId> 
  9.     <artifactId>slf4j-api</artifactId> 
  10.     <version>1.7.5</version> 
  11.     <scope>compile</scope> 
  12. </dependency> 



      在Maven管理的项目src/test/resource/下创建default-data.xml 

 
 
  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <dataset> 
  3.  
  4.     <!-- 注意,此处的user代表表名(database table name) --> 
  5.     <user id="1" username="123" password="456"/> 
  6.     <user id="2" username="123" password="456"/> 
  7.     <user id="3" username="123" password="456"/> 
  8.     <user id="4" username="123" password="456"/> 
  9.     <user id="5" username="123" password="456"/> 
  10. </dataset> 


      以下代码为提取后的BaseTest 

 
 
  1. package com.accentrix.ray;  
  2.  
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileWriter;  
  6. import java.io.InputStream;  
  7.  
  8. import javax.sql.DataSource;  
  9.  
  10. import org.dbunit.database.DatabaseDataSourceConnection;  
  11. import org.dbunit.database.IDatabaseConnection;  
  12. import org.dbunit.database.QueryDataSet;  
  13. import org.dbunit.dataset.DataSetException;  
  14. import org.dbunit.dataset.IDataSet;  
  15. import org.dbunit.dataset.xml.FlatXmlDataSet;  
  16. import org.dbunit.dataset.xml.FlatXmlProducer;  
  17. import org.dbunit.operation.DatabaseOperation;  
  18. import org.junit.AfterClass;  
  19. import org.junit.BeforeClass;  
  20. import org.xml.sax.InputSource;  
  21.  
  22. public class BaseTest {  
  23.     public static IDatabaseConnection connection;  
  24.     public static DataSource dataSource;  
  25.     private File temp;  
  26.  
  27.     @BeforeClass 
  28.     public static void init() throws Exception {  
  29.  
  30.         // 通过DataSource获取DataBaseSourceConnection  
  31.         connection = new DatabaseDataSourceConnection(dataSource);  
  32.     }  
  33.  
  34.     @AfterClass 
  35.     public static void destroy() throws Exception {  
  36.         if (connection != null) {  
  37.             connection.close();  
  38.         }  
  39.     }  
  40.  
  41.     protected IDataSet getDataSet(String name) throws DataSetException {  
  42.         // 通过类加载器获取default-data.xml文件的内容  
  43.         InputStream is = this.getClass().getClassLoader()  
  44.                 .getResourceAsStream(name + ".xml");  
  45.  
  46.         // IDataSet就类似是一个数据的容器,把default-data.xml内容  
  47.         // 转换成了DBUnit可识别的数据返回出去  
  48.         return new FlatXmlDataSet(new FlatXmlProducer(new InputSource(is)));  
  49.     }  
  50.  
  51.     protected void backupAll() throws Exception {  
  52.         // createDataSet代表从数据库中获取到DataSet,此时DataSet为数据库的内容  
  53.         IDataSet ds = connection.createDataSet();  
  54.  
  55.         // 创建临时文件  
  56.         temp = File.createTempFile("temp""xml");  
  57.  
  58.         // 将数据库内容的DataSet写入临时文件当中  
  59.         FlatXmlDataSet.write(ds, new FileWriter(temp), "UTF-8");  
  60.     }  
  61.  
  62.     protected void backupCustom(String... tableName) throws Exception {  
  63.         // 此种形式能保存某几张表的的数据,而不需要全部备份  
  64.         QueryDataSet qds = new QueryDataSet(connection);  
  65.         for (String str : tableName) {  
  66.             qds.addTable(str);  
  67.         }  
  68.         temp = File.createTempFile("temp""xml");  
  69.         FlatXmlDataSet.write(qds, new FileWriter(temp), "UTF-8");  
  70.     }  
  71.  
  72.     protected void recover() throws Exception {  
  73.  
  74.         // 获取数据库内容的临时文件生成DataSet  
  75.         IDataSet ds = new FlatXmlDataSet(new FlatXmlProducer(new InputSource(  
  76.                 new FileInputStream(temp))));  
  77.  
  78.         // 使用DatabaseOperation的枚举方法先清空数据库内容再还原数据库  
  79.         DatabaseOperation.CLEAN_INSERT.execute(connection, ds);  
  80.     }  
  81. }  
  82.  


      以下为单元测试类 

 
 
  1. package com.accentrix.ray;  
  2.  
  3. import static org.junit.Assert.assertEquals;  
  4. import static org.junit.Assert.assertNotNull;  
  5.  
  6. import org.dbunit.dataset.IDataSet;  
  7. import org.dbunit.operation.DatabaseOperation;  
  8. import org.junit.Test;  
  9.  
  10. public class TestUser extends BaseTest {  
  11.  
  12.     @Test 
  13.     public void testGetUser() throws Exception {  
  14.         // 首先获取到default-data.xml文件中的内容  
  15.         IDataSet ds = getDataSet("default-data.xml");  
  16.  
  17.         // 调用backupAll方法保存数据库表  
  18.         backupAll();  
  19.  
  20.         // 将default-data.xml中的内容替换成数据库的内容  
  21.         DatabaseOperation.CLEAN_INSERT.execute(connection, ds);  
  22.  
  23.         // 进行单元测试逻辑的判断  
  24.         User user = userService.get(1);  
  25.  
  26.         assertNotNull(user);  
  27.         assertEquals(user.getId(), new Integer(1));  
  28.         assertEquals(user.getPassword(), "456");  
  29.         assertEquals(user.getUsername(), "123");  
  30.  
  31.         // 最后进行数据库的恢复  
  32.         // 当然我们也可以将backupAll和recover放在@Before和@After当中  
  33.         recover();  
  34.     }  
  35.  
  36. }  
  37.  



总结: 
      使用了DBUnit后可以实现了对数据库的隔离,成功弥补了JUnit单元测试不清理数据现场的缺憾,实际上DBUnit只是简单的在单元测试前把数据库的数据进行了备份然后插入xml中配置好的数据,在测试结束后再用备份好的原数据库数据填充回数据库.但当面对复杂的表关系和大数据量的时候,每次进行测试都进行数据的备份,也是一个很大的负担,而且把全部的测试数据都编写在xml当中也是很大的工作量 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值