單一測試用例的 setUp()/tearDown() 僅能共享固件於該用例內部。若多個測試用例需共用相同環境(如資料庫連線),必須將固件抽取為獨立類別。JBuilder 2005 提供四種預定義固件:
getConnection()、runSqlFile() 等測試導向方法。本文重點示範 JDBC 與比較固件的建立與應用。
建立 JDataStore 資料庫 hr.jds(路徑 <專案目錄>/db/hr.jds),帳號 sysdba/123456。資料表 EMPLOYEE 包含 ID(String)、NAME(String)、AGE(int) 三欄位,預置 3 筆測試資料。
// Employee.java
package chapter25.db;
public class Employee {
private String id, name;
private int age;
public Employee(String id, String name, int age) { ... }
// getter、equals() 略
}
// EmployeeDAO.java
package chapter25.db;
import java.sql.*;
public class EmployeeDAO {
private Connection conn;
public EmployeeDAO(Connection conn) { this.conn = conn; }
public Employee findById(String id) throws SQLException {
String sql = "select * from employee where id ='" + id + "'";
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery(sql);
if (rs.next()) return new Employee(id, rs.getString("name"), rs.getInt("age"));
return null;
}
}
File → New... → Test → JDBC Fixture,類別名 HrJdbcFixture。設定驅動程式 com.borland.datastore.jdbc.DataStoreDriver,URL 指向 hr.jds,帳密 sysdba/123456,測試連線成功後完成。
產生的固件繼承 com.borland.jbuilder.unittest.JdbcFixture,核心方法包括 getConnection()、runSqlFile()、dumpResultSet() 等。
package fixture;
import java.sql.*;
import com.borland.jbuilder.unittest.JdbcFixture;
public class HrJdbcFixture extends JdbcFixture {
public HrJdbcFixture(Object obj) {
super();
super.setUrl("jdbc:borland:dslocal:D:/JTJB2005/chapter25/db/hr.jds");
super.setDriver("com.borland.datastore.jdbc.DataStoreDriver");
super.setUsername("sysdba");
super.setPassword("123456");
}
public void setUp() { super.setUp(); }
public void tearDown() { super.tearDown(); }
}
提示: 需手動將 JDataStore 類庫加入專案類路徑,否則執行時會拋 ClassNotFoundException。
建立 insert.sql 放置於 <專案目錄>/db/insert.sql:
delete from employee;
insert into employee values('0004','大山',23);
insert into employee values('0005','英華',30);
insert values('0006','柯明',31);
測試前先清空資料表、再插入固定資料,確保測試環境一致性。
對 EmployeeDAO 建立測試用例 TestEmployeeDAO,精靈第 3 步選擇 HrJdbcFixture。修改 setUp() 先初始化固件、取得連線、執行 insert.sql,再實例化 DAO:
protected void setUp() throws Exception {
super.setUp();
hrJdbcFixture = new HrJdbcFixture(this);
hrJdbcFixture.setUp();
employeeDAO = new EmployeeDAO(hrJdbcFixture.getConnection());
hrJdbcFixture.runSqlFile("D:/JTJB2005/chapter25/db/insert.sql", true);
}
public void testFindById() throws SQLException {
Employee expectEmp = new Employee("0004", "大山", 23);
Employee realEmp = employeeDAO.findById("0004");
assertNotNull(realEmp);
assertEquals(expectEmp, realEmp);
}
執行測試,固件先備妥環境,再驗證 findById() 正確性。
File → New... → Test → Comparision Fixture,類別名 ComparisonFixture1,啟用 Echo output to console 與 Verbose output,模式設為 UPDATE。
package fixture;
import com.borland.jbuilder.unittest.TestRecorder;
public class ComparisonFixture1 extends TestRecorder {
public ComparisonFixture1(Object obj) {
super();
super.setMode(UPDATE);
super.setVerbose(true);
super.setEcho(true);
String fileName = super.constructFilename("D:/JTJB2005/chapter25/test", obj);
super.setOutputFile(fileName);
}
public void setUp() {}
public void tearDown() {}
}
建立 TestEmployee 測試用例,僅保留 ComparisonFixture1 固件。測試邏輯:先記錄原物件 ID 與物件本身,再建立新物件比對:
public void testEmployee() {
String id = "0004", name = "王五"; int age = 23;
comparisonFixture1.print(employee.getId());
comparisonFixture1.recordObject(employee);
employee = new Employee(id, name, age);
assertTrue(comparisonFixture1.print(employee.getId()));
assertTrue(comparisonFixture1.compareObject(employee));
}
執行後,測試輸出標籤頁顯示詳細資訊,同目錄下產生無副檔名的輸出檔案 Employee,供下次比對使用。
| 模式 | 行為 |
|---|---|
| UPDATE | 比對目前輸出與既有檔案,檔案不存在則建新檔記錄。 |
| COMPARE | 僅比對,不更新檔案。 |
| RECORD | 記錄目前輸出,覆蓋既有檔案。 |
| OFF | 關閉比較功能。 |
注意: 修改測試邏輯後需重新初始化輸出檔:先設為 RECORD 執行一次,再改回 UPDATE。
print(String) / println(String):列印字串,若模式為 RECORD 且內容不同則回傳 false。recordObject(Object):記錄物件供後續 compareObject() 比對。compareObject(Object):呼叫傳入物件的 equals() 與已記錄物件比較。