TestExecutionListener 配置
TestExecutionListener Configuration
Spring 提供了以下默认注册的 TestExecutionListener 实现类,它们的注册顺序正好如下:
ServletTestExecutionListener: 为WebApplicationContext配置 Servlet API 的模拟对象(mocks)。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的配置重置模拟对象(mocks)。
注册 TestExecutionListener 实现
你可以通过使用@TestExecutionListeners注解,为测试类、其子类及其嵌套类显式注册TestExecutionListener实现。有关详细信息和示例,请参阅注解支持以及[javadoc中关于[TestExecutionListeners]的文档(https://docs.spring.io/spring-framework/docs/7.0.3/javadoc-api/org/springframework/test/context/TestExecutionListeners.html)。
切换到默认的 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属性文件中,通过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实现。
为了避免必须关注并重新声明所有默认监听器,你可以将@TestExecutionListeners的mergeMode属性设置为MergeMode.MERGE_WITH_DEFAULTS。MERGE_WITH_DEFAULTS表示本地声明的监听器应与默认监听器合并。合并算法会确保列表中的重复项被移除,并且合并后的监听器集合会根据AnnotationAwareOrderComparator的语义进行排序,具体内容如Ordering TestExecutionListener Implementations中所描述。如果某个监听器实现了Ordered接口或被@Order注解所标记,那么它就可以影响自己与默认监听器合并时的位置。否则,在合并时,本地声明的监听器将被添加到默认监听器的列表的末尾。
例如,如果在之前的例子中,MyCustomTestExecutionListener 类将其 order 值(例如 500)配置为小于 ServletTestExecutionListener 的 order 值(该值恰好是 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...
}