在數據庫代碼測試中,一般情況使用2種方案:
一是使用mock objects;
二是使用DbUnit。
mock objects基于物理隔離層的概念,將涉及到數據庫操作的代碼,全用虛擬對象代替。這種方案,對業務領域里的代碼來講是可行的,也比較方便,但對于數據庫操作層,此方案無用武之地,因為我們必須實實在在地與數據庫打交道。
而在數據庫測試中,因為我們力求將每個TestCase中眾多的測試方法完全隔離起來,不會因為一個測試方法因測試增加、刪除功能而影響到另一個測試方法,這樣,在每一個測試之前,數據庫的狀態是否穩定,甚至是完全不變,就顯得很重要了。而這點,正是數據庫測試的難點。
Dbunit解決了這個問題。其原理很簡單,就是在每個測試方法之前后,通過增刪一些固定的記錄,保持了數據庫的固定狀態,由此,我們可以在每個測試方法中自由地增刪記錄,而不用擔心會影響到別的測試方法。
但Dbunit也有一個問題,即它不能刪除非空的外鍵記錄。舉例來說,假設“員工”表中有一非空字段為“部門編號”,引用了“部門”表的id, 只要“員工”表存在任一記錄,“部門”表將不能被刪除,強行刪除將出現違犯約束(constraint violation)的異常。當然,假如必要,我們可以將數據庫的約束條件改為連鎖刪除,這樣,一旦我們刪除一名員工記錄,其所在的部門記錄也將從“部門”表中刪除。而此又會導致“員工”表中所有該部門的員工全被刪除。這是絕對不答應的。當然,作為測試,我們可以先刪除“員工”表,再刪除“部門”表。
但有時,某些表自己引用自己,如“組織”表中有一“上級組織編號”字段,是自己“組織編號”的外鍵,即,此字段引用了本表中其他記錄的“組織編號”。此時,我們必須先將這些引用了其他記錄的“組織編號”的記錄先刪除,才能刪除此表中的其他記錄。而Dbunit在實現上,只是用了一個簡單的"delete from ..."的SQL語句,不能解決這個問題。
Dbunit的原理是如此簡單,我們完全可以設計的“Dbunit”,通過多重循環語句,干脆利落地刪除自引用的整表。我們的“Dbunit”,可以命名為“SqlRunner”。
package com.sarkuya.util.database;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SqlRunner {
static {
try {
Class.forName("org.hsqldb.jdbcDriver");
} catch (ClassNotFoundException ex) {
ex.PRintStackTrace();
}
}
public static void executeUpdate(String sql) {
Connection conn;
Statement stmt;
try {
conn = DriverManager.getConnection("jdbc:hsqldb:mem:testingdb", "sa", "");
stmt = conn.createStatement();
stmt.executeUpdate(sql);
stmt.close();
conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
public static boolean isUndeletableForSelfReference (String 表名, String 字段名) {
Connection conn;
Statement stmt;
boolean result = true;
try {
conn = DriverManager.getConnection("jdbc:hsqldb:mem:testingdb", "sa", "");
stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select count(*) from " + 表名 + " where " + 字段名 + " is not null");
rs.next();
if (rs.getInt(1) != 0) {
result = true;
}
else {
result = false;
}
rs.close();
stmt.close();
conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
return result;
}
新聞熱點
疑難解答