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...
}