TestExecutionListener 配置

Spring 預設按以下確切順序註冊以下 TestExecutionListener 實現:

  • ServletTestExecutionListener: 為 WebApplicationContext 配置 Servlet API mock 物件。

  • DirtiesContextBeforeModesTestExecutionListener: 處理 "before" 模式的 @DirtiesContext 註解。

  • ApplicationEventsTestExecutionListener: 提供 ApplicationEvents 支援。

  • BeanOverrideTestExecutionListener: 提供 測試中的 Bean 覆蓋 支援。

  • DependencyInjectionTestExecutionListener: 為測試例項提供依賴注入。

  • MicrometerObservationRegistryTestExecutionListener: 提供 Micrometer 的 ObservationRegistry 支援。

  • DirtiesContextTestExecutionListener: 處理 "after" 模式的 @DirtiesContext 註解。

  • CommonCachesTestExecutionListener: 如有必要,清除測試的 ApplicationContext 中的資源快取。

  • TransactionalTestExecutionListener: 提供帶有預設回滾語義的事務性測試執行。

  • SqlScriptsTestExecutionListener: 執行使用 @Sql 註解配置的 SQL 指令碼。

  • EventPublishingTestExecutionListener: 將測試執行事件釋出到測試的 ApplicationContext (參見 測試執行事件)。

  • MockitoResetTestExecutionListener: 重置由 @MockitoBean@MockitoSpyBean 配置的 mock 物件。

註冊 TestExecutionListener 實現

可以使用 @TestExecutionListeners 註解為測試類、其子類和其巢狀類明確註冊 TestExecutionListener 實現。有關詳細資訊和示例,請參閱註解支援@TestExecutionListeners 的 Javadoc。

切換回預設的 TestExecutionListener 實現

如果擴充套件了帶有 @TestExecutionListeners 註解的類,並且需要切換回使用預設的監聽器集,可以使用以下註解對類進行註解。

  • Java

  • Kotlin

// Switch to default listeners
@TestExecutionListeners(
	listeners = {},
	inheritListeners = false,
	mergeMode = MERGE_WITH_DEFAULTS)
class MyTest extends BaseTest {
	// class body...
}
// Switch to default listeners
@TestExecutionListeners(
	listeners = [],
	inheritListeners = false,
	mergeMode = MERGE_WITH_DEFAULTS)
class MyTest : BaseTest {
	// class body...
}

預設 TestExecutionListener 實現的自動發現

使用 @TestExecutionListeners 註冊 TestExecutionListener 實現適用於在有限測試場景中使用的自定義監聽器。但是,如果自定義監聽器需要在整個測試套件中使用,則可能會變得很麻煩。透過 SpringFactoriesLoader 機制支援自動發現預設 TestExecutionListener 實現,解決了這個問題。

例如,spring-test 模組在其 META-INF/spring.factories 屬性檔案中,在 org.springframework.test.context.TestExecutionListener 鍵下聲明瞭所有核心預設 TestExecutionListener 實現。第三方框架和開發人員可以透過自己的 spring.factories 檔案以同樣的方式,將自己的 TestExecutionListener 實現新增到預設監聽器列表中。

TestExecutionListener 實現的排序

當 TestContext Framework 透過上述 SpringFactoriesLoader 機制發現預設 TestExecutionListener 實現時,例項化的監聽器會使用 Spring 的 AnnotationAwareOrderComparator 進行排序,該比較器遵循 Spring 的 Ordered 介面和 @Order 註解進行排序。AbstractTestExecutionListener 和 Spring 提供的所有預設 TestExecutionListener 實現都以適當的值實現了 Ordered。因此,第三方框架和開發人員應透過實現 Ordered 或宣告 @Order 來確保其預設 TestExecutionListener 實現以正確的順序註冊。有關每個核心監聽器分配的值的詳細資訊,請參閱核心預設 TestExecutionListener 實現的 getOrder() 方法的 Javadoc。

合併 TestExecutionListener 實現

如果透過 @TestExecutionListeners 註冊了自定義 TestExecutionListener,則不會註冊預設監聽器。在最常見的測試場景中,這實際上強制開發人員除了任何自定義監聽器之外,還必須手動宣告所有預設監聽器。以下列表演示了這種配置風格

  • Java

  • Kotlin

@ContextConfiguration
@TestExecutionListeners({
	MyCustomTestExecutionListener.class,
	ServletTestExecutionListener.class,
	DirtiesContextBeforeModesTestExecutionListener.class,
	DependencyInjectionTestExecutionListener.class,
	DirtiesContextTestExecutionListener.class,
	TransactionalTestExecutionListener.class,
	SqlScriptsTestExecutionListener.class
})
class MyTest {
	// class body...
}
@ContextConfiguration
@TestExecutionListeners(
	MyCustomTestExecutionListener::class,
	ServletTestExecutionListener::class,
	DirtiesContextBeforeModesTestExecutionListener::class,
	DependencyInjectionTestExecutionListener::class,
	DirtiesContextTestExecutionListener::class,
	TransactionalTestExecutionListener::class,
	SqlScriptsTestExecutionListener::class
)
class MyTest {
	// class body...
}

這種方法的挑戰在於,它要求開發人員確切知道預設註冊了哪些監聽器。此外,預設監聽器集可能會在不同版本之間發生變化 — 例如,SqlScriptsTestExecutionListener 在 Spring Framework 4.1 中引入,DirtiesContextBeforeModesTestExecutionListener 在 Spring Framework 4.2 中引入。此外,像 Spring Boot 和 Spring Security 這樣的第三方框架透過上述自動發現機制註冊它們自己的預設 TestExecutionListener 實現。

為了避免不得不瞭解和重新宣告所有預設監聽器,可以將 @TestExecutionListenersmergeMode 屬性設定為 MergeMode.MERGE_WITH_DEFAULTSMERGE_WITH_DEFAULTS 表示本地宣告的監聽器應與預設監聽器合併。合併演算法確保從列表中刪除重複項,並且根據TestExecutionListener 實現的排序中所述的 AnnotationAwareOrderComparator 的語義對合並後的最終監聽器集進行排序。如果監聽器實現了 Ordered 或帶有 @Order 註解,它可以影響其與預設值合併時的位置。否則,本地宣告的監聽器在合併時會追加到預設監聽器列表的末尾。

例如,如果前面示例中的 MyCustomTestExecutionListener 類配置其 order 值(例如,500)小於 ServletTestExecutionListener 的順序(恰好是 1000),則 MyCustomTestExecutionListener 可以自動與預設列表合併,位於 ServletTestExecutionListener 之前,並且前面的示例可以替換為以下內容:

  • Java

  • Kotlin

@ContextConfiguration
@TestExecutionListeners(
	listeners = MyCustomTestExecutionListener.class,
	mergeMode = MERGE_WITH_DEFAULTS
)
class MyTest {
	// class body...
}
@ContextConfiguration
@TestExecutionListeners(
		listeners = [MyCustomTestExecutionListener::class],
		mergeMode = MERGE_WITH_DEFAULTS
)
class MyTest {
	// class body...
}