TestExecutionListener Configuration

Spring 提供了以下 TestExecutionListener 实现,这些实现已在默认情况下按如下顺序注册:

Spring provides the following TestExecutionListener implementations that are registered by default, exactly in the following order:

  • ServletTestExecutionListener: Configures Servlet API mocks for a WebApplicationContext.

  • DirtiesContextBeforeModesTestExecutionListener: Handles the @DirtiesContext annotation for “before” modes.

  • ApplicationEventsTestExecutionListener: Provides support for ApplicationEvents.

  • DependencyInjectionTestExecutionListener: Provides dependency injection for the test instance.

  • MicrometerObservationRegistryTestExecutionListener: Provides support for Micrometer’s ObservationRegistry.

  • DirtiesContextTestExecutionListener: Handles the @DirtiesContext annotation for “after” modes.

  • CommonCachesTestExecutionListener: Clears resource caches in the test’s ApplicationContext if necessary.

  • TransactionalTestExecutionListener: Provides transactional test execution with default rollback semantics.

  • SqlScriptsTestExecutionListener: Runs SQL scripts configured by using the @Sql annotation.

  • EventPublishingTestExecutionListener: Publishes test execution events to the test’s ApplicationContext (see Test Execution Events).

Registering TestExecutionListener Implementations

您可以使用 @TestExecutionListeners 注释为测试类、其子类及其嵌套类明确注册 TestExecutionListener 实现。请参阅 annotation support 及https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/context/TestExecutionListeners.html[@TestExecutionListeners] 中的 javadoc 以了解详情和示例。

You can register TestExecutionListener implementations explicitly for a test class, its subclasses, and its nested classes by using the @TestExecutionListeners annotation. See annotation support and the javadoc for @TestExecutionListeners for details and examples.

Switching to default TestExecutionListener implementations

如果您扩展了一个使用 @TestExecutionListeners 进行标注的类,并且需要切换为使用默认的侦听器集,则可以使用以下内容对您的类进行标注。

If you extend a class that is annotated with @TestExecutionListeners and you need to switch to using the default set of listeners, you can annotate your class with the following.

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

Automatic Discovery of Default TestExecutionListener Implementations

使用 @TestExecutionListeners 注册 TestExecutionListener 实现适用于在受限的测试场景中使用的自定义侦听器。但是,如果需要在整个测试套件中使用自定义侦听器,这样做可能很繁琐。这一问题可通过通过 SpringFactoriesLoader 机制自动发现用于的 TestExecutionListener 实现来解决。

Registering TestExecutionListener implementations by using @TestExecutionListeners is suitable for custom listeners that are used in limited testing scenarios. However, it can become cumbersome if a custom listener needs to be used across an entire test suite. This issue is addressed through support for automatic discovery of default TestExecutionListener implementations through the SpringFactoriesLoader mechanism.

例如,spring-test 模块在https://github.com/spring-projects/spring-framework/tree/main/spring-test/src/main/resources/META-INF/spring.factories[META-INF/spring.factories]属性文件中的 org.springframework.test.context.TestExecutionListener 键初始化中声明了所有核心默认 TestExecutionListener 实现。第三方框架和开发人员可以通过其自己的 spring.factories 文件以相同的方式将自己的 TestExecutionListener 实现添至默认侦听器列表。

For example, the spring-test module declares all core default TestExecutionListener implementations under the org.springframework.test.context.TestExecutionListener key in its META-INF/spring.factories properties file. Third-party frameworks and developers can contribute their own TestExecutionListener implementations to the list of default listeners in the same manner through their own spring.factories files.

Ordering TestExecutionListener Implementations

当 TestContext 框架通过aforementionedSpringFactoriesLoader 机制发现默认 TestExecutionListener 实现时,实例化侦听器将通过 Spring 的 AnnotationAwareOrderComparator 进行排序,AnnotationAwareOrderComparator 遵循 Spring 的 Ordered 接口和`@Order` 注释来进行排序。AbstractTestExecutionListener 和所有由 Spring 提供的默认`TestExecutionListener` 实现都使用适当的值实现 Ordered 。因此,第三方框架和开发人员应当确保他们的默认`TestExecutionListener` 实现通过实现 Ordered 或声明 @Order 按正确的顺序注册。有关分配给每个核心侦听器的值,请参见核心默认`TestExecutionListener` 实现的 getOrder() 方法的 javadoc。

When the TestContext framework discovers default TestExecutionListener implementations through the aforementioned SpringFactoriesLoader mechanism, the instantiated listeners are sorted by using Spring’s AnnotationAwareOrderComparator, which honors Spring’s Ordered interface and @Order annotation for ordering. AbstractTestExecutionListener and all default TestExecutionListener implementations provided by Spring implement Ordered with appropriate values. Third-party frameworks and developers should therefore make sure that their default TestExecutionListener implementations are registered in the proper order by implementing Ordered or declaring @Order. See the javadoc for the getOrder() methods of the core default TestExecutionListener implementations for details on what values are assigned to each core listener.

Merging TestExecutionListener Implementations

如果通过 @TestExecutionListeners 注册了自定义 TestExecutionListener,则不会注册默认监听器。在大多数常见的测试场景中,这实际上迫使开发人员手动声明所有默认监听器以及任何自定义监听器。以下列表演示了这种配置方式:

If a custom TestExecutionListener is registered via @TestExecutionListeners, the default listeners are not registered. In most common testing scenarios, this effectively forces the developer to manually declare all default listeners in addition to any custom listeners. The following listing demonstrates this style of configuration:

  • 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 中引入。此外,像 SpringBoot 和 Spring Security 这样的第三方框架会使用上述automatic discovery mechanism 来注册自己的默认`TestExecutionListener`实现。

The challenge with this approach is that it requires that the developer know exactly which listeners are registered by default. Moreover, the set of default listeners can change from release to release — for example, SqlScriptsTestExecutionListener was introduced in Spring Framework 4.1, and DirtiesContextBeforeModesTestExecutionListener was introduced in Spring Framework 4.2. Furthermore, third-party frameworks like Spring Boot and Spring Security register their own default TestExecutionListener implementations by using the aforementioned automatic discovery mechanism .

为避免必须知道和重新声明所有默认侦听器,你可以将 @TestExecutionListenersmergeMode 属性设置为 MergeMode.MERGE_WITH_DEFAULTSMERGE_WITH_DEFAULTS 指示应该将本地声明的侦听器与默认侦听器合并。合并算法确保从列表中删除重复项,并确保所得合并的侦听器集根据 AnnotationAwareOrderComparator 的语义进行排序,如 xref:testing/testcontext-framework/tel-config.adoc#testcontext-tel-config-ordering[Ordering TestExecutionListener 实现中所述。如果侦听器实现 Ordered 或使用 @Order 注释,它可以影响合并到默认侦听器的相应位置。否则,在合并时本地声明的侦听器会追加到默认侦听器列表。

To avoid having to be aware of and re-declare all default listeners, you can set the mergeMode attribute of @TestExecutionListeners to MergeMode.MERGE_WITH_DEFAULTS. MERGE_WITH_DEFAULTS indicates that locally declared listeners should be merged with the default listeners. The merging algorithm ensures that duplicates are removed from the list and that the resulting set of merged listeners is sorted according to the semantics of AnnotationAwareOrderComparator, as described in Ordering TestExecutionListener Implementations. If a listener implements Ordered or is annotated with @Order, it can influence the position in which it is merged with the defaults. Otherwise, locally declared listeners are appended to the list of default listeners when merged.

例如,如果前一个示例中的 MyCustomTestExecutionListener 类将其 order 值(例如,500)配置为小于 ServletTestExecutionListener(恰好为 1000)的顺序,则 MyCustomTestExecutionListener 随后可以自动与默认值列表合并为 ServletTestExecutionListener 之前,并且上一个示例可以替换为以下内容:

For example, if the MyCustomTestExecutionListener class in the previous example configures its order value (for example, 500) to be less than the order of the ServletTestExecutionListener (which happens to be 1000), the MyCustomTestExecutionListener can then be automatically merged with the list of defaults in front of the ServletTestExecutionListener, and the previous example could be replaced with the following:

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