採用極限編程(XP)的開發團隊深知單元測試的價值:代碼更乾淨、重構更大膽、開發更快速。但當測試目標依賴系統狀態(如遠端 EJB、Web Service、資料庫)時,即使最資深的測試駕駛開發者也會感到棘手。本文將探討如何結合 Mock 物件 與 AspectJ,打造精準且健壯的單元測試方案。
以 `ClientBean` 為例,它委派 `CustomerManager EJB` 執行查詢與註冊業務。傳統 JUnit 測試(清單 3)直接依賴真實 EJB 環境,導致:
Mock 物件以測試專用實作替換真實協作者,驗證被測類與其交互正確性。例如 `Deleter.delete(Collection)` 測試中,`MockDeletable` 記錄 `delete()` 是否被呼叫(清單 5-6)。
面向對象機制限制了 Mock 的適用範圍:
AspectJ 的連接點模型允許在「每測試案例」基礎上修改上下文行為,甚至在禁止 Mock 的場景下實現乾淨替換。
替換 `Context.lookup()` 回傳 Mock Home 物件(清單 8-10),無需部署 EJB 即可運行測試,適合早期開發或依賴不可控的第三方服務。
保留 EJB 部署,僅替換 `CustomerManager` 的業務方法呼叫(清單 11-12),配合 Cactus 在容器內執行,可驗證配置正確性。
透過 Ant 建構檔指定不同 Aspect 清單(清單 13),編譯時切換測試策略,生產代碼零污染。利用 AspectJ 的 Introduction(介紹) 機制,動態讓測試類繼承 `ServletTestCase` 以支援 Cactus(清單 14)。
AspectJ 的橫切能力補足了 OO 模式在全域資源替換上的缺口,讓開發者能以增量方式編寫無需管理系統資料的單元測試。雖然引入 AOP 概念需學習成本,但本文展示的模式易於掌握,且能顯著提升測試的精準度與維護性。