DbUnit设计理念:
熟悉单元测试的开发人员都知道,在对数据库进行单元测试时候,通常采用的方案有运用模拟对象(mock objects)。通过隔离关联的数据库访问类,比如JDBC的相关操作类,来达到对数据库操作的模拟测试。但是如果真正要测试访问数据结果正确性那么就显得力不从心了。
DBUnit的设计理念就是在测试之前,备份数据库,然后给对象数据库植入我们需要的准备数据。
DBUnit是对JUnit的一种扩展,开发人员可以通过创建测试用例代码,在这些测试用例的生命周期内来对数据库的操作结果进行比较。
DBUnit通过使用用户自定义的数据集以及相关操作使数据库处于一种可知的状态,从而使得测试自动化、可重复和相对独立。
使用spring的AbstractTransactionalDataSourceSpringContextTests。在每个testcase开始之前,会自动开启一个事务,然后在结束的时候进行事务回滚。这样就可以隔绝几个测试用例之间的相互干扰。这很重要,才能够实现测试的自动化
DbUnit测试基本概念和流程
基于DbUnit 的测试的主要接口是IDataSet。IDataSet代表一个或多个表的数据。
可以将数据库模式的全部内容表示为单个IDataSet 实例。这些表本身由Itable 实例来表示。
IDataSet 的实现有很多,每一个都对应一个不同的数据源或加载机制。最常用的几种 IDataSet实现为:
FlatXmlDataSet:数据的简单平面文件 XML 表示
QueryDataSet:用 SQL 查询获得的数据
DatabaseDataSet:数据库表本身内容的一种表示
XlsDataSet :数据的excel表示
在每个testcase开始之前以及结束之后,执行的数据库操作为以下:
一般而言,使用DbUnit进行单元测试的流程如下:
1 根据业务,做好测试用的准备数据和预想结果数据,通常准备成xml格式文件。
2 在setUp()方法里边备份数据库中的关联表。
3 在setUp()方法里边读入准备数据。
4 对测试类的对应测试方法进行实装:执行对象方法,把数据库的实际执行结果和预想结果进行比较。
。
问题如下:
<?xml version='1.0' encoding='UTF-8'?> <dataset> <T a="1" b="1" /> <T a="2" b="2" c="2"/> </dataset>
以上为用来测试的数据,但是执行测试读取数据时,如果表T数据首行未初始化'c'这个字段的话那么表T所有'c'字段数据均为NULL,为了解决该问题,查了下dbunit 的API,发现里面给了明确解决方案,但代码有些问题,稍微改改,很快解决,供大家分享。版本:2.4.8
不多说,上代码:
private IDataSet[] getDataSets(String[] files) throws DataSetException, IOException {
if (files == null)
return null;
IDataSet[] datasets = new IDataSet[files.length];
PathMatchingResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver();
for (int i = 0; i < files.length; i++) {
Resource[] resources = resourceResolver.getResources(files[i]);
for (Resource resource : resources) {
FlatXmlDataSetBuilder builder = new FlatXmlDataSetBuilder();
builder.setColumnSensing(true);
ReplacementDataSet ds = new ReplacementDataSet(builder.build(resource.getInputStream()));
ds.addReplacementObject("[NULL]", null);
ds.addReplacementObject("[null]", null);
datasets[i] = ds;
}
}
return datasets;
}
这个方法专用来返回IDataSet[] ,相信大家知道该方法的作用了,修改之处主要在建立FlatXmlDataSetBuilder 对象上,然后为其setColumnSensing(true);然后执行其build方法,哦了!
跑测试吧。