單元測試與整合測試在軟體開發流程中佔據核心地位。開發者透過測試驗證程式正確性,管理者透過持續整合與覆蓋率分析保障軟體品質。Spring 作為企業級 Java 應用的標準配置,不僅實現低耦合,更簡化了與 Hibernate、Struts 等框架的整合。本文將詳細介紹如何在 Spring 生態系統中高效實施單元測試。
以一個基於 Spring 的帳號管理系統為例,包含 AccountService(業務層)與 AccountDao(資料存取層),透過 Spring XML 管理依賴。傳統 JUnit 測試需手動載入 Spring 上下文、手動獲取 Bean、手動清理測試資料:
@BeforeClass
public static void init() {
ApplicationContext context = new ClassPathXmlApplicationContext("config/spring-db-old.xml");
service = (AccountService)context.getBean("accountService");
}
@Test
public void testGetAccountById() {
// 測試邏輯...
finally { service.removeAccount(acct); } // 手動清理
}
缺點明顯:樣板代碼多、無法使用依賴注入、事務管理需手動處理。
@Autowired)@Transactional)指定 Spring 專用的 JUnit 運行器,標準化測試環境。
指定 Spring 配置來源,支援 XML 路徑或配置類:
@ContextConfiguration("/config/spring-db1.xml")
// 或使用 Java Config
@ContextConfiguration(classes = SpringDb2Config.class)
啟用自動事務管理,測試完成自動回滾,無需手動清理資料。
測試類同樣受 Spring 容器管理,可直接注入被測試 Bean。
Spring 3.0 引入基於 Java 的配置方式,需引入 CGLIB:
@Configuration
public class SpringDb2Config {
@Autowired private DriverManagerDataSource dataSource;
@Bean public Initializer initer() { return new Initializer(); }
@Bean public AccountDao accountDao() {
AccountDao dao = new AccountDao();
dao.setDataSource(dataSource);
return dao;
}
@Bean public AccountService accountService() { return new AccountService(); }
}
當測試修改了 ApplicationContext(如動態註冊 Bean),標註此註解強制重新載入上下文。可標註在類或方法上。
自訂事務管理器 Bean 名稱與預設回滾行為:
@TransactionConfiguration(transactionManager="myTxManager", defaultRollback=false) @Rollback(true) // 方法級覆寫
@Test(expected=Exception.class):預期拋出異常@Test(timeout=毫秒):超時控制@Repeat(n):重複執行 n 次同一 XML 定義多環境 Bean,測試時啟用特定 Profile:
<beans profile="test">...</beans>
<beans profile="production">...</beans>
@ActiveProfiles("test")
繼承 AbstractTransactionalTestNGSpringContextTests 或使用 @TestExecutionListeners 引入監聽器即可獲得相同功能。
核心組件:
執行流程:測試啟動 → 建立 TestContextManager → 載入 ApplicationContext → 截獲 BeforeClass/Before/After/AfterClass 事件 → 通知對應監聽器執行 DI、事務等邏輯。
Spring TestContext 框架極大簡化了 Spring 應用的測試工作,消除樣板代碼,提供自動 DI 與事務管理,並支援現代化配置方式。若您的專案使用 Spring,強烈建議採用此框架提升測試效率與品質。