驗證呼叫預存程序 LUCK_LOAD_COMMON(?, ?) 的 DAO 方法,模擬 Connection 與 CallableStatement 行為,不需真實資料庫。
public String getNumber() {
CallableStatement cstmt = null;
try {
cstmt = conn.prepareCall("{call LUCK_LOAD_COMMON(?,?)}");
cstmt.setString(1, "1");
cstmt.registerOutParameter(2, Types.VARCHAR);
cstmt.executeUpdate();
return cstmt.getString(2);
} catch (Exception e) { return null; }
finally { if (cstmt != null) try { cstmt.close(); } catch (Exception ignore) {} }
}
// 1. 建立 Mock 物件與控制器
MockControl connCtrl = MockControl.createControl(Connection.class);
Connection mockConn = (Connection) connCtrl.getMock();
MockControl cstmtCtrl = MockControl.createControl(CallableStatement.class);
CallableStatement mockCstmt = (CallableStatement) cstmtCtrl.getMock();
// 2. 錄製預期呼叫序列
mockConn.prepareCall("{call LUCK_LOAD_COMMON(?,?)}");
connCtrl.setReturnValue(mockCstmt); // 回傳 mock CallableStatement
connCtrl.replay();
mockCstmt.setString(1, "1");
mockCstmt.registerOutParameter(2, Types.VARCHAR);
mockCstmt.executeUpdate();
cstmtCtrl.setReturnValue(1); // executeUpdate 回傳 1
mockCstmt.getString(2);
cstmtCtrl.setReturnValue("5,4,3"); // 回傳預期結果
mockCstmt.close();
cstmtCtrl.replay();
// 3. 注入 mockConn 給 DAO 並執行測試
dao.setConnection(mockConn);
String result = dao.getNumber();
Assert.assertEquals("5,4,3", result);
// 4. 驗證所有預期呼叫均發生
connCtrl.verify();
cstmtCtrl.verify();
setReturnValue() 定義回傳值。replay() 後,Mock 進入驗證模式,實際代碼呼叫若與錄製不符(參數、順序、次數)即拋出 AssertionFailedError。verify() 確認所有預期均被滿足。若預存程序 SQL 字串寫錯(如多一個 ?),EasyMock 會精確報錯:
Unexpected method call prepareCall("{call LUCK_LOAD_COMMON(?,?,?)}"): expected: 0, actual: 1
這證明 EasyMock 能有效捕捉 SQL 字串拼接錯誤。