測試中的 Bean 覆寫

測試中的 Bean 覆寫指的是,透過註解測試類別中的一個或多個欄位,來覆寫測試類別之 ApplicationContext 中的特定 Bean 的能力。

此功能旨在作為一種風險較低的替代方案,以取代透過 @Bean 註冊 Bean,並將 DefaultListableBeanFactorysetAllowBeanDefinitionOverriding 標誌設定為 true 的做法。

Spring TestContext 框架為 Bean 覆寫提供了兩組註解。

前者純粹依賴 Spring,而後者則依賴 Mockito 第三方程式庫。

自訂 Bean 覆寫支援

上述三個註解建立在 @BeanOverride 元註解和相關基礎架構之上,這讓使用者能夠定義自訂的 Bean 覆寫變體。

若要實作自訂 Bean 覆寫支援,需要以下項目:

  • 一個使用 @BeanOverride 元註解的註解,用於定義要使用的 BeanOverrideProcessor

  • 自訂 BeanOverrideProcessor 實作。

  • 由處理器建立的一個或多個具體 BeanOverrideHandler 實作。

Spring TestContext 框架包含以下 API 的實作,這些 API 支援 Bean 覆寫,並負責設定基礎架構的其餘部分。

  • 一個 BeanFactoryPostProcessor

  • 一個 ContextCustomizerFactory

  • 一個 TestExecutionListener

spring-test 模組在其 META-INF/spring.factories 屬性檔中註冊了後兩者(BeanOverrideContextCustomizerFactoryBeanOverrideTestExecutionListener)的實作。

Bean 覆寫基礎架構會在測試類別中搜尋使用 @BeanOverride 元註解的任何欄位,並實例化相應的 BeanOverrideProcessor,後者負責建立適當的 BeanOverrideHandler

內部 BeanOverrideBeanFactoryPostProcessor 接著會使用 Bean 覆寫處理器,透過建立、替換或包裝 Bean 來變更測試的 ApplicationContext,如相應的 BeanOverrideStrategy 所定義。

取代

取代 Bean。如果對應的 Bean 不存在,則拋出例外。

取代或建立

如果 Bean 存在則取代它。如果對應的 Bean 不存在,則建立一個新的 Bean。

包裝

檢索原始 Bean 並包裝它。

只有 *singleton* Bean 可以被覆寫。任何嘗試覆寫非 singleton Bean 的行為都會導致例外。

當取代由 FactoryBean 建立的 Bean 時,FactoryBean 本身將被替換為與適用 BeanOverrideHandler 建立的 Bean 覆寫實例對應的 singleton Bean。

當包裝由 FactoryBean 建立的 Bean 時,將會包裝由 FactoryBean 建立的物件,而不是 FactoryBean 本身。

與 Spring 的自動裝配機制(例如,解析 @Autowired 欄位)相比,TestContext 框架中的 Bean 覆寫基礎架構在定位 Bean 時,可以執行的啟發式方法有限。BeanOverrideProcessor 可以計算要覆寫的 Bean 名稱,或者根據註解欄位的類型及其限定註解,可以明確地選取 Bean。

通常,Bean 是由 BeanOverrideFactoryPostProcessor「依類型」選取的。或者,使用者可以直接在自訂註解中提供 Bean 名稱。

BeanOverrideProcessor 實作也可能在內部根據慣例或其他方法計算 Bean 名稱。