乐趣区

关于spring:Spring-5-中文解析核心篇集成测试之TestContext上

Spring TestContext 框架(位于 org.springframework.test.context 包中)提供了通用的、注解驱动的单元和集成测试反对,这些反对与所应用的测试框架无关。TestContext框架还非常重视约定优于配置,你能够通过基于注解的配置笼罩正当的默认值。

除了通用测试根底构造之外,TestContext框架还为 JUnit 4,JUnit Jupiter(AKA JUnit 5)和 TestNG 提供了显式反对。对于 JUnit 4 和 TestNG,Spring 提供了形象反对类。此外,Spring 为 JUnit 4 提供了自定义 JUnit Runner 和自定义 JUnit 规定,以及 JUnit Jupiter 的自定义扩大,可让你编写所谓的 POJO 测试类。不须要 POJO 测试类来扩大特定的类层次结构,例如形象反对类。下一节概述了 TestContext 框架的外部。如果你仅对应用框架感兴趣,而对应用本人的自定义监听器或自定义加载程序进行扩大不感兴趣,请间接转到配置(上下文治理、依赖项注入、事务管理、反对类和注解反对局部。

3.5.1 要害形象

该框架的外围由 TestContextManager 类和 TestContextTestExecutionListenerSmartContextLoader接口组成。为每个测试类创立一个 TestContextManager(例如,用于在 JUnit Jupiter 中的单个测试类中执行所有测试方法)。反过来,TestContextManager 治理蕴含以后测试上下文的 TestContext。随着测试的进行,TestContextManager 还更新了 TestContext 的状态,并委托给 TestExecutionListener 实现,该实现通过提供依赖项注入,治理事务等来检测理论的测试执行。SmartContextLoader负责为给定的测试类加载ApplicationContext。无关更多信息和各种实现的示例,请参见 javadoc 和 Spring 测试套件。

TestContext

TestContext封装了在其中执行测试的上下文(与应用中的理论测试框架无关),并为其负责的测试实例提供了上下文治理和缓存反对。如果须要,TestContext还委托给 SmartContextLoader 来加载ApplicationContext

TestContextManager

TestContextManager是 Spring TestContext 框架的次要入口点,并负责管理单个 TestContext 并在定义良好的测试执行点向每个注册的 TestExecutionListener 收回事件信号:

  • 在任何 before 类之前或在特定测试框架的所有办法之前。
  • 测试实例后处理。
  • 在任何 before 或在每个特定测试框架的办法之前。
  • 在执行测试方法之前但在测试设置之后。
  • 在测试方法执行之后,但在测试装配之前。
  • 之后的任何办法或之后的每一个特定的测试框架。
  • 在特定测试框架的任何类后或所有办法之后。

TestExecutionListener

TestExecutionListener定义用于对由注册监听器的 TestContextManager 公布的测试执行事件做出反馈的 API。请参阅 TestExecutionListener 配置。

上下文加载器

ContextLoader是一个策略接口,用于为 Spring TestContext 框架治理的集成测试加载 ApplicationContext。你应该实现SmartContextLoader 而不是此接口,以提供对组件类,激活的 bean 定义配置文件、测试属性源、上下文层次结构和 WebApplicationContext 反对的反对。

SmartContextLoaderContextLoader 接口的扩大,它取代了原始的最小 ContextLoader SPI。具体来说,SmartContextLoader 能够抉择解决资源地位、组件类或上下文初始化器。此外,SmartContextLoader能够在其加载的上下文中设置激活 Bean 定义配置文件并测试属性源。

Spring 提供了以下实现:

  • DelegatingSmartContextLoader: 它是两个默认加载器之一,它在外部委派给 AnnotationConfigContextLoaderGenericXmlContextLoaderGenericGroovyXmlContextLoader,具体取决于为测试类申明的配置或默认地位或默认配置类的存在。仅当 Groovy 在类门路上时才启用 Groovy 反对。
  • WebDelegatingSmartContextLoader: 它是两个默认加载器之一,它在外部委派给 AnnotationConfigWebContextLoader、GenericXmlWebContextLoader 或GenericGroovyXmlWebContextLoader,具体取决于为测试类申明的配置或默认地位或默认配置类的存在。仅当测试类上存在@WebAppConfiguration 时,才应用 Web ContextLoader。仅当 Groovy 在类门路上时才启用 Groovy 反对。
  • AnnotationConfigContextLoader: 从组件类加载规范ApplicationContext
  • AnnotationConfigWebContextLoader: 从组件类加载WebApplicationContext
  • GenericGroovyXmlContextLoader: 从 Groovy 脚本或 XML 配置文件的资源地位加载规范ApplicationContext
  • GenericGroovyXmlWebContextLoader: 从 Groovy 脚本或 XML 配置文件的资源地位加载WebApplicationContext
  • GenericXmlContextLoader: 从 XML 资源地位加载规范ApplicationContext
  • GenericXmlWebContextLoader: 从 XML 资源地位加载WebApplicationContext
  • GenericPropertiesContextLoader:从 Java 属性文件加载规范ApplicationContext
3.5.2 疏导 TestContext 框架

Spring TestContext 框架外部的默认配置足以满足所有常见用例。然而,有时开发团队或第三方框架心愿更改默认的 ContextLoader,实现自定义的TestContextContextCache,扩大默认的 ContextCustomizerFactoryTestExecutionListener实现等等。为了对 TestContext 框架的运行形式进行低级别管制,Spring 提供了疏导策略。

TestContextBootstrapper定义了用于疏导 TestContext 框架的 SPI。TestContextManager应用 TestContextBootstrapper 加载以后测试的 TestExecutionListener 实现并构建它治理的 TestContext。你能够间接应用@BootstrapWith 或作为元注解,为测试类(或测试类层次结构)配置自定义疏导策略。如果没有通过应用 @BootstrapWith 显式配置疏导程序,则依据 @WebAppConfiguration 的存在,应用 DefaultTestContextBootstrapperWebTestContextBootstrapper

因为 TestContextBootstrapper SPI 未来可能会更改(以适应新的需要),咱们强烈建议实现者不要间接实现此接口,而应扩大AbstractTestContextBootstrapper 或其具体子类之一。

3.5.3 TestExecutionListener配置

Spring 提供了以下 TestExecutionListener 实现,这些实现默认状况下按以下程序注册:

  • ServletTestExecutionListener: 为 WebApplicationContext 配置 Servlet API 模仿。
  • DirtiesContextBeforeModesTestExecutionListener: 解决 before 模式的 @DirtiesContext 注解。
  • DependencyInjectionTestExecutionListener: 为测试实例提供依赖项注入。
  • DirtiesContextTestExecutionListener: 解决 after 模式的 @DirtiesContext 注解。
  • TransactionalTestExecutionListener: 提供具备默认回滚语义的事务测试执行。
  • SqlScriptsTestExecutionListener: 运行应用 @Sql 正文配置的 SQL 脚本。
  • EventPublishingTestExecutionListener: 将测试执行事件公布到测试的 ApplicationContext 中(请参阅测试执行事件)。

注册 TestExecutionListener 实现

你能够应用 @TestExecutionListeners 注解为测试类及其子类注解 TestExecutionListener 实现。无关详细信息和示例,请参见注解反对和 @TestExecutionListeners 的 javadoc。

默认 TestExecutionListener 实现主动发现

通过应用 @TestExecutionListeners 注册 TestExecutionListener 实现实用于无限测试计划中应用的自定义监听器。然而,如果须要在整个测试套件中应用自定义监听器,则会变得很麻烦。通过 SpringFactoriesLoader 机制反对主动发现默认的 TestExecutionListener 实现,能够解决这个问题。

具体来说,spring-test模块在其 META-INF/spring.factories 属性文件中的 keyorg.springframework.test.context.TestExecutionListener下申明所有外围默认 TestExecutionListener 实现。第三方框架和开发人员能够通过本人的 META-INF/spring.factories 属性文件以雷同的形式将本人的 TestExecutionListener 实现奉献到默认监听器列表中。

TestExecutionListener 程序实现

TestContext 框架通过上述 SpringFactoriesLoader 机制发现默认 TestExecutionListener 实现时,实例化的监听器将应用 Spring 的 AnnotationAwareOrderComparator 进行排序,该类将应用 Spring 的 Ordered 接口和 @Order 注解进行排序。Spring 提供的 AbstractTestExecutionListener 和所有默认的 TestExecutionListener 实现以适当的值实现 Ordered。因而,第三方框架和开发人员应通过施行Ordered 或申明 @Order 来确保按默认程序注册其默认的 TestExecutionListener 实现。请参阅 javadoc 以获取外围默认 TestExecutionListener 实现的 getOrder() 办法,以获取无关为每个外围监听器调配哪些值的详细信息。

TestExecutionListener 合并实现

如果通过 @TestExecutionListeners 注册了自定义TestExecutionListener,则不会注册默认监听器。在大多数常见的测试计划中,这无效地迫使开发人员手动申明除任何自定义监听器之外的所有默认监听器。

上面的清单演示了这种配置款式:

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

这种办法的挑战在于,它要求开发人员确切地晓得默认状况下注册了哪些监听器。此外,默认的监听器集能够随版本的不同而变动 - 例如,在 Spring 框架 4.1 中引入了 SqlScriptsTestExecutionListener,在 Spring 框架 4.2 中引入了DirtiesContextBeforeModesTestExecutionListener。此外,诸如 Spring Boot 和 Spring Security 之类的第三方框架通过应用上述主动发现机制注册了本人的默认TestExecutionListener 实现。

为防止必须理解并从新申明所有默认监听器,能够将 @TestExecutionListenersmergeMode属性设置为 MergeMode.MERGE_WITH_DEFAULTSMERGE_WITH_DEFAULTS 示意应将本地申明的监听器与默认监听器合并。合并算法可确保从列表中删除反复项,并确保依据 AnnotationAwareOrderComparator 的语义对合并后的监听器集进行排序,如 Ordering TestExecutionListener 实现中所述。如果监听器实现 Ordered 或应用 @Order 进行注解,则它能够影响将其与默认值合并的地位。否则,合并时,本地申明的监听器将追加到默认侦听器列表中。

例如,如果上一个示例中的 MyCustomTestExecutionListener 类将程序值(例如 500)配置为小于 ServletTestExecutionListener 的程序(恰好是 1000),则 MyCustomTestExecutionListener 能够主动与默认列表合并。在 ServletTestExecutionListener 后面,并且后面的示例能够替换为以下示例:

@ContextConfiguration
@TestExecutionListeners(
    listeners = MyCustomTestExecutionListener.class,
    mergeMode = MERGE_WITH_DEFAULTS
)
class MyTest {// class body...}
3.5.4 测试执行事件

Spring 框架 5.2 中引入的 EventPublishingTestExecutionListener 提供了一种实现自定义 TestExecutionListener 的代替办法。测试的 ApplicationContext 中的组件能够监听 EventPublishingTestExecutionListener 公布的以下事件,每个事件都与TestExecutionListener API 中的办法绝对应。

  • BeforeTestClassEvent
  • PrepareTestInstanceEvent
  • BeforeTestMethodEvent
  • BeforeTestExecutionEvent
  • AfterTestExecutionEvent
  • AfterTestMethodEvent
  • AfterTestClassEvent

只有当 ApplicationContext 曾经加载时,才会公布这些事件。

这些事件可能因为各种起因被应用,例如重置模仿 bean 或跟踪测试执行。应用测试执行事件而不是实现自定义 TestExecutionListener 的一个劣势是,测试执行事件能够由在测试 ApplicationContext 中注册的任何 Spring bean 所应用,并且此类 bean 能够间接受害于依赖项注入和 ApplicationContext 的其余性能。相同,TestExecutionListenerApplicationContext 中不是 bean。

为了监听测试执行事件,Spring Bean 能够抉择实现 org.springframework.context.ApplicationListener 接口。或者,能够应用 @EventListener 注解监听器办法,并将监听办法配置为监听下面列出的特定事件类型之一(请参阅基于注解的事件监听器)。因为这种办法的风行,Spring 提供了以下专用的 @EventListener 注解,以简化测试执行事件监听器的注册。这些注解驻留在 org.springframework.test.context.event.annotation 包中。

  • @BeforeTestClass
  • @PrepareTestInstance
  • @BeforeTestMethod
  • @BeforeTestExecution
  • @AfterTestExecution
  • @AfterTestMethod
  • @AfterTestClass

参考代码:org.liyong.test.annotation.test.spring.TestExecutionEventTest

异样解决

默认状况下,如果测试执行事件监听器在应用事件时抛出异样,则该异样将流传到应用中的根底测试框架(例如 JUnit 或 TestNG)。例如,如果应用 BeforeTestMethodEvent 导致异样,则相应的测试方法将因异样而失败。相同,如果异步测试执行事件监听器引发异样,则该异样不会流传到根底测试框架。无关异步异样解决的更多详细信息,请查阅 @EventListener 类级 javadoc。

异步监听器

如果你心愿特定的测试执行事件监听器异步处理事件,你能够应用 Spring 的惯例 @Async 反对。无关更多详细信息,请查阅 @EventListener 的类级 javadoc。

参考代码:org.liyong.test.annotation.test.spring.TestExecutionEventTest

作者

集体从事金融行业,就任过易极付、思建科技、某网约车平台等重庆一流技术团队,目前就任于某银行负责对立领取零碎建设。本身对金融行业有强烈的喜好。同时也实际大数据、数据存储、自动化集成和部署、散布式微服务、响应式编程、人工智能等畛域。同时也热衷于技术分享创建公众号和博客站点对常识体系进行分享。关注公众号:青年 IT 男 获取最新技术文章推送!

博客地址: http://youngitman.tech

CSDN: https://blog.csdn.net/liyong1…

微信公众号:

技术交换群:

退出移动版