开始
1. 用DBTestCase的子类建立数据库
2. 用你自己的TestCase子类建立数据库
3. 数据库数据校验
4. DbUnit的Ant任务和Canoo web测试(此处省略,另详)
用DBTestCase的子类建立数据库
第一步:创建你的dataset文件
你的测试需要一些数据。这就意味着你必须创建dataset。许多情况下你都是处理xml的dataset。你可以人工凑一些一般的xml dataset或是从你的数据库中导出一个xml dataset.
第二步:继承DBTestCase类
现在你要创建一个测试类。最简单的方式是用通过继承DbUnit的DBTestCase来创建你自己的测试类。DBTestCase继承了Junit的TestCase类。一个模板方法你需要实现,getDataSet()返回你在第一步创建的dataset。DBTestCase依靠IdatabaseTester来工作,默认的配置是使用PropertiesBaseJdbcDatabaseTester,它是用系统属性来指出DriverManager的配置。最简单的方式是在你测试类的构造函数中配置它。你可以通过覆盖getDatabaseTester()方法来修改它的行为。
使用下面提供的三种IDatabaseTester之一实现,你也可以使用下面表中描述的DBTestCase的其它子类。
JdbcBaseDBTestCase
|
使用DriverManager来创建连接(在JdbcDatabaseTester的帮助下)
|
DataSourceBasedDBTestCase
|
使用javax.sql.DataSource来创建连接(在DataSourceDatabaseTester的帮助下)
|
JndiBasedDBTestCase
|
使用javax.sql.DataSourece通过JNDI定位(在jndiDatabaseTester的帮助下)
|
下面是一个简单的实现,连接到一个Hypersonic数据库并返回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"));
}
}
第三步:(可选)实现getSetUpOperation()和getTearDownOperation()方法
默认的情况,DbUnit在每次执行test之前执行一个CLEAN_INSERT操作并且不之后不执行清除操作。你可以通过覆盖getSetUpOperation()和getTearDownOperation()来改变这个行为。
下面这个例子演示你可以通过简单的覆盖方法改变执行测试前和后。
public class SampleTest extends DBTestCase
{
protected DatabaseOperation getSetUpOperation() throws Exception
{
return DatabaseOperation.REFRESH;
}
protected DatabaseOperation getTearDownOperation() throws Exception
{
return DatabaseOperation.NONE;
}
}
第四步:实现你的testXXX()方法
就像你使用JUit一样实现test方法。你的数据库在测试方法之前初始化并且在测试之后清除,这取决于你在前几步是怎么做的。
用你自己的TestCase子类建立数据库
为了使用DbUnit你不是必须要继承DBTestCase类。你可以覆盖标准的Junit的SetUp()方法,执行你所需要的数据库操作。如果你要执行清除,同样覆盖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来完成同样的功能。就像前面所提到过的,DBTestCase内部是使用IdatabaseTester来实现的。你的测试类可以使用这个功能操作数据集(DataSets)。目前有4个方便的实现。
JdbcDatabaseTester
|
使用DriverManager来创建连接。
|
PropertiesBasedJdbcDatabaseTester
|
也是使用DriverManager来创建连接,但是配置信息是从系统属性中读取的。这是DBTestCase的默认实现方式。
|
DataSourceDatabaseTester
|
使用javax.sql.DataSource创建连接。
|
JndiDatabaseTester
|
使用javax.sql.DataSource通过JNDI寻找
|
你也可以提供你自己的IdatabaseTester实现,推荐使用AbstractDatabaseTester作为一个开始点。
例:
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();
}
}
数据库数据校验
DbUnit提供校验两个表或是数据集是否包含相同的数据的方法。下面的两个方法是在执行测试类的时候可以校验你的数据库中是否包含预期的数据。
public class Assertion
{
public static void assertEquals(ITable expected, ITable actual)
public static void assertEquals(IDataSet expected, IDataSet actual)
}
例子
以下例子,展示怎么比较一个数据库表的快照和一个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数据集是一个数据库的快照可以和你想要比较的expected数据集进行比较。就象他的名字一样,expected数据集中包含预期的值。
expected数据集一定要和你建立数据库时的对象不一样。因为你需要两个数据集,一个是在测试之前建立数据库,一个是提供匹配测试时的expected数据。
使用查询来获取数据库的快照
你也可以校验查询的结果是不是和期望的数据集匹配。这个查询可以使查询一个表中的一部分也可以是多表的联合查询。
Itable actualJoinData = getConnection().createQueryTable("RESULT_NAME",
"SELECT * FROM TABLE1, TABLE2 WHERE ");
在比较的时候忽略一些列
有些时候希望忽视一些列来进行比较,特别是对主键,日期或是时间列,这些列的值是在测试的时候又代码产生的。一种方式是在你的expected表中省略你不想比较的列的声明。这样你可以过滤真实的数据库表只暴露出expected表中的列。
下面这些代码片段向你展示怎么过滤真实数据库中的表。首先,真实数据库中必须包含expected表中的所有列。另外,真实表中有这些列而expected表中没有这些列,这种情况是允许的。
ITable filteredTable = DefaultColumnFilter.includedColumnsTable(actual,
expected.getTableMetaData().getColumns());
Assertion.assertEquals(expected, filteredTable);
这个技术的主要限制是你不能在你的expected数据集XML中使用DTD。使用DTD的话你需要过滤expected表和真实表中的列。查看FAQ中关于在运行时排除一些表的列(excluding some table columns at runtime)。
行顺序
默认的情况下,用DbUnit得到的数据库快照表是按主键排序的。如果一个表没有主键或是主键是由数据库自动产生的,行的顺序是不确定的,那么assertEquals将会失败。
你一定要排序你的数据库快照通过在IdatabaseConnection.createQueryTable时手工加入”ORDER BY”语句。或者你可以这样使用SortedTable:
Assertion.assertEquals(new SortedTable(expected),
new SortedTable(actual, expected.getTableMetaData()));