TestExecutionListener 配置

Infra 提供了以下默认注册的 TestExecutionListener 实现,顺序如下:

  • MockTestExecutionListener:为 WebApplicationContext 配置 Servlet API 模拟对象。

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

  • ApplicationEventsTestExecutionListener:提供对 ApplicationEvents 的支持。

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

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

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

  • CommonCachesTestExecutionListener:如果需要,清除测试 ApplicationContext 中的资源缓存。

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

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

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

注册 TestExecutionListener 实现

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

切换到默认的 TestExecutionListener 实现

如果您扩展了一个使用 @TestExecutionListeners 注解的类,并且需要切换到使用默认的监听器集,则可以使用以下内容注解您的类。

  • Java

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

自动发现默认 TestExecutionListener 实现

使用 @TestExecutionListeners 注册 TestExecutionListener 实现适用于在有限测试场景中使用的自定义监听器。 但是,如果需要在整个测试套件中使用自定义监听器,则会变得很麻烦。 这个问题通过 InfraFactoriesLoader 机制支持自动发现默认 TestExecutionListener 实现来解决。

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

TestExecutionListener 实现排序

当 TestContext 框架通过 上述 InfraFactoriesLoader 机制发现默认 TestExecutionListener 实现时,实例化的监听器使用 Infra AnnotationAwareOrderComparator 进行排序,该比较器支持 Infra Ordered 接口和 @Order 注解进行排序。 AbstractTestExecutionListener 和 Infra 提供的所有默认 TestExecutionListener 实现都实现了具有适当值的 Ordered。 因此,第三方框架和开发人员应确保通过实现 Ordered 或声明 @Order 以正确的顺序注册其默认 TestExecutionListener 实现。 有关分配给每个核心监听器的值的详细信息,请参阅核心默认 TestExecutionListener 实现的 getOrder() 方法的 javadoc。

合并 TestExecutionListener 实现

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

  • Java

@ContextConfiguration
@TestExecutionListeners({
  MyCustomTestExecutionListener.class,
  ServletTestExecutionListener.class,
  DirtiesContextBeforeModesTestExecutionListener.class,
  DependencyInjectionTestExecutionListener.class,
  DirtiesContextTestExecutionListener.class,
  TransactionalTestExecutionListener.class,
  SqlScriptsTestExecutionListener.class
})
class MyTest {
  // 类体...
}

这种方法的挑战在于,它要求开发人员确切知道默认注册了哪些监听器。 此外,默认监听器集可能会随版本而变化——例如,SqlScriptsTestExecutionListener 是在 TODAY Framework 4.1 中引入的,而 DirtiesContextBeforeModesTestExecutionListener 是在 TODAY Framework 4.2 中引入的。 此外,像 Infra Boot 和 Infra Security 这样的第三方框架使用上述 自动发现机制 注册它们自己的默认 TestExecutionListener 实现。

为了避免必须了解并重新声明所有默认监听器,您可以将 @TestExecutionListenersmergeMode 属性设置为 MergeMode.MERGE_WITH_DEFAULTSMERGE_WITH_DEFAULTS 指示本地声明的监听器应与默认监听器合并。 合并算法确保从列表中删除重复项,并且生成的合并监听器集根据 AnnotationAwareOrderComparator 的语义进行排序,如 TestExecutionListener 实现排序 中所述。 如果监听器实现了 Ordered 或使用 @Order 进行了注解,它可以影响其与默认值合并的位置。 否则,本地声明的监听器在合并时将追加到默认监听器列表的末尾。

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

  • Java

@ContextConfiguration
@TestExecutionListeners(
  listeners = MyCustomTestExecutionListener.class,
  mergeMode = MERGE_WITH_DEFAULTS
)
class MyTest {
  // 类体...
}