TestExecutionListener 配置

Spring 提供以下默认注册的TestExecutionListener 实现,其顺序如下所示:

  • ServletTestExecutionListener:为WebApplicationContext配置 Servlet API 模拟。

  • 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配置的模拟。

注册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 框架通过上述SpringFactoriesLoader机制发现默认的TestExecutionListener实现时,实例化的侦听器将使用 Spring 的AnnotationAwareOrderComparator进行排序,该排序器会遵守 Spring 的Ordered接口和@Order注解进行排序。AbstractTestExecutionListener和 Spring 提供的所有默认TestExecutionListener实现都使用适当的值实现了Ordered。因此,第三方框架和开发人员应确保其默认的TestExecutionListener实现通过实现Ordered或声明@Order以正确的顺序注册。有关为每个核心侦听器分配了哪些值的详细信息,请参阅核心默认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表示本地声明的监听器应该与默认监听器合并。合并算法确保从列表中删除重复项,并且生成的合并监听器集根据AnnotationAwareOrderComparator的语义排序,如TestExecutionListener实现的排序中所述。如果监听器实现了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...
}