@TestBean

@TestBean 用於測試類中的非靜態欄位上,以使用工廠方法提供的例項覆蓋測試的 ApplicationContext 中的特定 bean。

關聯的工廠方法名稱派生自帶註解欄位的名稱,如果指定了 bean 名稱則使用 bean 名稱。工廠方法必須是 static 的,不接受任何引數,並且返回型別必須與要覆蓋的 bean 的型別相容。為了更明確,或者如果你更喜歡使用不同的名稱,該註解允許提供一個特定的方法名稱。

預設情況下,帶註解欄位的型別用於搜尋要覆蓋的候選 bean。如果多個候選 bean 匹配,可以提供 @Qualifier 來縮小要覆蓋的候選 bean 範圍。或者,如果候選 bean 的名稱與欄位名稱匹配,也會匹配。

如果對應的 bean 不存在,將會建立一個 bean。但是,如果你希望在對應的 bean 不存在時測試失敗,可以將 enforceOverride 屬性設定為 true,例如 @TestBean(enforceOverride = true)

要使用按名稱覆蓋而不是按型別覆蓋,請指定該註解的 name 屬性。

Qualifier(包括欄位名稱)用於確定是否需要建立一個單獨的 ApplicationContext。如果你在多個測試中使用此功能來覆蓋同一個 bean,請確保欄位名稱保持一致,以避免建立不必要的上下文。

@TestBean@ContextHierarchy 結合使用可能會導致不良結果,因為預設情況下,每個 @TestBean 將應用於所有上下文層級級別。為了確保特定的 @TestBean 僅應用於單個上下文層級級別,請將 contextName 屬性設定為與配置的 @ContextConfiguration 名稱匹配,例如 @TestBean(contextName = "app-config")

有關更多詳細資訊和示例,請參閱帶有 bean 覆蓋的上下文層級結構

@TestBean 欄位或工廠方法的可見性沒有限制。

因此,此類欄位和方法可以是 publicprotected、包私有(預設可見性)或 private,具體取決於專案的需求或編碼實踐。

以下示例展示瞭如何使用 @TestBean 註解的預設行為

  • Java

class OverrideBeanTests {
	@TestBean (1)
	CustomService customService;

	// test case body...

	static CustomService customService() { (2)
		return new MyFakeCustomService();
	}
}
1 標記一個欄位以覆蓋型別為 CustomService 的 bean。
2 此靜態方法的結果將用作例項並注入到該欄位中。

在上面的示例中,我們正在覆蓋型別為 CustomService 的 bean。如果存在多個該型別的 bean,則會考慮名稱為 customService 的 bean。否則,測試將失敗,你需要提供某種 qualifier 來標識要覆蓋哪個 CustomService bean。

以下示例使用按名稱查詢,而不是按型別查詢

  • Java

class OverrideBeanTests {
	@TestBean(name = "service", methodName = "createCustomService") (1)
	CustomService customService;

	// test case body...

	static CustomService createCustomService() { (2)
		return new MyFakeCustomService();
	}
}
1 標記一個欄位以覆蓋名稱為 service 的 bean,並指定工廠方法名稱為 createCustomService
2 此靜態方法的結果將用作例項並注入到該欄位中。

為了找到要呼叫的工廠方法,Spring 會搜尋聲明瞭 @TestBean 欄位的類、其超類之一或任何實現的介面。如果 @TestBean 欄位宣告在 @Nested 測試類中,也會搜尋包含類的層級結構。

或者,可以透過其完全限定方法名稱引用外部類中的工廠方法,語法為 <fully-qualified class name>#<method name>,例如 methodName = "org.example.TestUtils#createCustomService"

只有 singleton bean 可以被覆蓋。任何覆蓋非 singleton bean 的嘗試都將導致異常。

覆蓋由 FactoryBean 建立的 bean 時,FactoryBean 將被替換為與 @TestBean 工廠方法返回的值相對應的 singleton bean。