DBUnit是基於Junit的,DBUnit的單元測試類繼承DBTestCase即可,DBTestCase的繼承關係如圖一所示
下面就以一個例子來簡述DBunit在單元測試類中的配置。
public class DataAccessContext_Part1_Test extends DBTestCase {
public DataAccessContext_Part1_Test(String name){
super(name);
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, DBUnitCommon.DRIVER);
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, DBUnitCommon.CONNECTIONSTR);
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, DBUnitCommon.DBUSERNAME);
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, DBUnitCommon.DBPWD);
}
//構造函數
@Before
public void setUp() throws Exception {
super.setUp();
}
@After
public void tearDown() throws Exception {
super.tearDown();
}
@SuppressWarnings("static-access")
protected void setUpDatabaseConfig(DatabaseConfig config) {
config.setProperty(config.PROPERTY_DATATYPE_FACTORY,new PostgresqlDataTypeFactory());
}
@Override
protected IDataSet getDataSet() throws Exception {
return new FlatXmlDataSetBuilder().build(new FileInputStream("export.xml"));
}
--------------------------
單元測試用例
--------------------------
}
一 構造函數部分
單元測試類需提供一個含一個String類型參數的構造函數。因為Junit的TestCase類提供需要這個函數,其源碼如下:
/**
* the name of the test case
*/
private String fName;
/**
* No-arg constructor to enable serialization. This method
* is not intended to be used by mere mortals without calling setName().
*/
public TestCase() {
fName= null;
}
/**
* Constructs a test case with the given name.
*/
public TestCase(String name) {
fName= name;
}
/**
* Override to run the test and assert itsstate.
* @throws Throwable if any exception is thrown
*/
protected voidrunTest() throws Throwable {
assertNotNull("TestCase.fNamecannot be null", fName); // Some VMs crash when callinggetMethod(null,null);
MethodrunMethod= null;
try{
//use getMethod to get all public inherited
//methods. getDeclaredMethods returns all
//methods of this class but excludes the
//inherited ones.
runMethod=getClass().getMethod(fName, (Class[])null);
}catch (NoSuchMethodException e) {
fail("Method\""+fName+"\" not found");
}
if(!Modifier.isPublic(runMethod.getModifiers())) {
fail("Method\""+fName+"\" should be public");
}
try{
runMethod.invoke(this);
}
catch(InvocationTargetException e) {
e.fillInStackTrace();
throwe.getTargetException();
}
catch(IllegalAccessException e) {
e.fillInStackTrace();
throwe;
}
}
遺憾的是DBUnit 官網上沒有對這個參數作出解釋,我也沒有看出來這個參數是必需的,如果哪位前輩明白為什麼需要這個參數,望不吝賜教,先行謝過。
構造函數中其餘四條System.setProperty語句用來設置連接數據庫必要參數,望文知義,不再贅述。
二 setup()方法
該方法在JUnit中用來在每一個單元測試用例運行前做一些準備工作,因為DBTestCase類的父類中這setUp函數中有一部分初始化工作,故DBUnit的單元測試方法必須重寫該方法並調用父類的setUp方法。
DBTestCase的setUp方法中的初始化工作源碼如下:
super.setUp();
finalIDatabaseTester databaseTester = getDatabaseTester();
assertNotNull( "DatabaseTester is not set", databaseTester );
databaseTester.setSetUpOperation( getSetUpOperation() );
databaseTester.setDataSet( getDataSet() );
databaseTester.setOperationListener(getOperationListener());
databaseTester.onSetup();
三 teardown()方法
該方法在Junit中用來在每一個單元測試用例運行後執行一些清理工作或其他邏輯,其理同上,其源碼如下:
try {
finalIDatabaseTester databaseTester = getDatabaseTester();
assertNotNull( "DatabaseTester is not set", databaseTester );
databaseTester.setTearDownOperation(getTearDownOperation() );
databaseTester.setDataSet( getDataSet() );
databaseTester.setOperationListener(getOperationListener());
databaseTester.onTearDown();
} finally {
tester = null;
super.tearDown();
}
四 setUpDatabaseConfig()方法
該方法用來設置數據庫方言。
五 getDataSet()方法
該方法用來讀取XML數據使數據庫或數據庫的某些表恢復至已知狀態。
六 DBUnit在運行每個單元測試用例之前的默認動作為CLEAN-INSERT,每個單元測試用例運行結束後的默認動作為NONE,即什麼也不做。如果我們有需求去更改這其默認動作,則需要重寫DataBaseTestCase中以下兩個方法:
/**
* Returns thedatabase operation executed in test setup.
*/
protectedDatabaseOperation getSetUpOperation() throws Exception
{
returnDatabaseOperation.CLEAN_INSERT;
}
/**
* Returns thedatabase operation executed in test cleanup.
*/
protectedDatabaseOperation getTearDownOperation() throws Exception
{
returnDatabaseOperation.NONE;
}
其全部的默認動作如圖二所示: