TestExecutionListener 配置

Spring提供了以下默认注册的TestExecutionListener实现,确切地按照以下顺序:

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

  • DirtiesContextBeforeModesTestExecutionListener: 处理“before”模式下的@DirtiesContext注解。

  • ApplicationEventsTestExecutionListener: 为ApplicationEvents提供支持。

  • DependencyInjectionTestExecutionListener: 为测试实例提供依赖注入。

  • MicrometerObservationRegistryTestExecutionListener: 为Micrometer的ObservationRegistry提供支持。

  • DirtiesContextTestExecutionListener: 处理“after”模式下的@DirtiesContext注解。

  • TransactionalTestExecutionListener: 提供具有默认回滚语义的事务测试执行。

  • SqlScriptsTestExecutionListener: 运行使用@Sql注解配置的SQL脚本。

  • EventPublishingTestExecutionListener: 将测试执行事件发布到测试的ApplicationContext(参见测试执行事件)。

注册TestExecutionListener实现

您可以通过使用@TestExecutionListeners注解为测试类、其子类和嵌套类显式注册TestExecutionListener实现。有关详细信息和示例,请参见注解支持@TestExecutionListeners的javadoc。

切换到默认的TestExecutionListener实现

如果您扩展了一个带有@TestExecutionListeners注解的类,并且需要切换到使用默认的监听器集合,您可以为您的类添加以下注解。

  • Java

  • Kotlin

// 切换到默认监听器
@TestExecutionListeners(
	listeners = {},
	inheritListeners = false,
	mergeMode = MERGE_WITH_DEFAULTS)
class MyTest extends BaseTest {
	// 类体...
}
// 切换到默认监听器
@TestExecutionListeners(
	listeners = [],
	inheritListeners = false,
	mergeMode = MERGE_WITH_DEFAULTS)
class MyTest : BaseTest {
	// 类体...
}

自动发现默认的TestExecutionListener实现

通过使用@TestExecutionListeners注册TestExecutionListener实现适用于在有限的测试场景中使用的自定义监听器。但是,如果一个自定义监听器需要在整个测试套件中使用,这种方式可能变得繁琐。通过SpringFactoriesLoader机制支持自动发现默认的TestExecutionListener实现来解决这个问题。

例如,spring-test模块在其META-INF/spring.factories属性文件中声明了所有核心默认的TestExecutionListener实现在org.springframework.test.context.TestExecutionListener键下。第三方框架和开发人员可以通过自己的spring.factories文件以相同的方式向默认监听器列表中贡献自己的TestExecutionListener实现。

排序TestExecutionListener实现

当TestContext框架通过上述SpringFactoriesLoader机制发现默认的TestExecutionListener实现时,实例化的监听器将使用Spring的AnnotationAwareOrderComparator进行排序,该排序遵循Spring的Ordered接口和@Order注解进行排序。Spring的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...
}