領先一步
VMware 提供培訓和認證,為您的發展注入動力。
瞭解更多Spring Framework 6.2.0-M1
已釋出,其中包含解決一百多個問題的更改。這些更改中包括 Spring 測試支援中的一系列新特性。
在這篇文章中,我想向大家介紹這些新測試特性中的一個:Bean 覆蓋支援。
使用 Spring TestContext Framework,您可以透過註解驅動的模型輕鬆地在整合測試中驗證 Spring 應用程式的正確連線。
在單元測試中,依賴注入和 Spring 設計原則使您的程式碼對容器的依賴性降低,並且更容易手動樁或模擬元件的依賴項以便進行隔離測試。在整合測試中,這一點不太相關,因為測試旨在覆蓋元件的正確連線。儘管您可能會發現在整合測試中需要替換 bean 的情況。
Spring Framework 團隊通常不建議重新定義 bean。儘管在 `BeanDefinitionRegistry` 的預設實現中透過一個標誌目前可以實現,但我們計劃棄用它,並且 Spring Boot 已經透過預設關閉 bean 覆蓋來選擇退出。
然而,這更多是生產程式碼中的擔憂,我們承認在測試中覆蓋 bean 是有用且合理的。因此,我們旨在為該領域常見的覆蓋場景提供一流的安排。
在 Spring Framework `6.2.0-M1` 中,我們引入了一個可擴充套件的 bean 覆蓋特性,它允許您在整合測試中精確且明確地替換一個或多個 bean 定義,同時防止生產程式碼或測試的其他部分出現此類意外更改。
@TestBean
進行簡單的基於方法的覆蓋Spring TestContext Framework 現在提供了一個簡單的 Bean 覆蓋支援實現:`@TestBean` 註解。
覆蓋名為 `example` 的 bean 分三步完成:新增一個與 bean 同名的欄位,用 `@TestBean` 註解它,並新增一個名為 `exampleTestOverride` 的無引數 `static` 工廠方法。在該工廠方法中,如果 bean 型別是介面,您可以返回一個簡化的實現,如下例所示:
@Configuration
class ProdConfiguration {
@Bean
MyService customService() {
return new ProdServiceImpl();
}
}
@SpringJUnitConfig
class MyServiceIntegrationTests {
@TestBean
MyService customService;
static MyService customServiceTestOverride() {
return new SimplifiedServiceImpl();
}
@Test
void test(ApplicationContext context) {
assertThat(context.getBean("customService")
.isSameAs(this.customService)
.isInstanceOf(SimplifiedServiceImpl.class);
//...
}
}
除非為 `@TestBean` 註解提供了 `beanName` 屬性,否則帶註解欄位的名稱將被解釋為目標 bean 的名稱。
`methodName` 引數也可用於指向不遵循預設命名約定 `{beanName}TestOverride` 的工廠方法。
Bean 覆蓋機制負責解析此註解並替換登錄檔中的現有 bean 定義。測試類中的 `customService` 欄位也會注入由 `customServiceTestOverride` 工廠方法生成的覆蓋例項。
@MockitoBean
和 @MockitoSpyBean
進行基於 Mockito 的覆蓋這第二個 bean 覆蓋實現基於 Mockito 庫。它帶有兩個註解:@MockitoBean
用於自動將目標單例 bean 替換為 mock,以及 @MockitoSpyBean
用於將 bean 包裝在 spy 中。
這些註解都包含 Mockito 特有的屬性,以便進一步配置目標 bean 如何進行 mocking。這包括支援指定 mock 在測試之間如何重置,如下例所示:
@Configuration
class ProdConfiguration {
@Bean
MyService customService() {
return new ProdService();
}
}
@SpringJUnitConfig
class MyServiceIntegrationTests {
@MockitoSpyBean(reset = MockReset.NONE)
MyService customService;
@Test
void test() {
//...
}
}
在上面的示例中,spy 在測試之間將不會重置。預設情況下,mock 和 spy 會在測試方法執行後重置。
請注意,要對 bean 進行 spy,首先必須存在被 spy 類的一個實際例項。Bean 覆蓋特性支援這種特殊情況,允許在 bean 例項化後從元資料建立覆蓋,此外還支援更常見的替換 bean 定義的情況。
新的測試中的 Bean 覆蓋支援採用基於註解的模型,適用於您測試類中的欄位。它是可擴充套件和可定製的,上面介紹的 3 個註解只是我們提供的預設實現。
實現您自己的 Bean 覆蓋方式就像實現以下內容一樣簡單:
Spring TestContext Framework 解析測試類,查詢任何用 `@BeanOverride` 元註解標記的欄位,並例項化相關的 `BeanOverrideProcessor` 以註冊一個 `OverrideMetadata` 例項。
然後 `BeanFactoryPostProcessor` 將使用該資訊修改上下文,根據每個元資料註冊和替換 bean 定義。
Spring TestContext Framework 現在提供了兩種在測試中覆蓋 bean 的方法,而沒有意外副作用的風險。bean 覆蓋機制是可擴充套件的,如果您更喜歡使用 Mockito 以外的 mocking 庫,這將非常方便。
我們期待社群對這項功能的反饋,包括對第一版改進的建議。
與此同時,程式設計愉快!