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
类和 TestContext
,TestExecutionListener
和SmartContextLoader
接口组成。为每个测试类创立一个 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
反对的反对。
SmartContextLoader
是 ContextLoader
接口的扩大,它取代了原始的最小 ContextLoader
SPI。具体来说,SmartContextLoader
能够抉择解决资源地位、组件类或上下文初始化器。此外,SmartContextLoader
能够在其加载的上下文中设置激活 Bean 定义配置文件并测试属性源。
Spring 提供了以下实现:
DelegatingSmartContextLoader
: 它是两个默认加载器之一,它在外部委派给AnnotationConfigContextLoader
、GenericXmlContextLoader
或GenericGroovyXmlContextLoader
,具体取决于为测试类申明的配置或默认地位或默认配置类的存在。仅当 Groovy 在类门路上时才启用 Groovy 反对。WebDelegatingSmartContextLoader
: 它是两个默认加载器之一,它在外部委派给AnnotationConfigWebContextLoader
、GenericXmlWebContextLoader 或GenericGroovyXmlWebContextLoader
,具体取决于为测试类申明的配置或默认地位或默认配置类的存在。仅当测试类上存在@WebAppConfiguration
时,才应用 WebContextLoader
。仅当 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
,实现自定义的TestContext
或ContextCache
,扩大默认的 ContextCustomizerFactory
和TestExecutionListener
实现等等。为了对 TestContext
框架的运行形式进行低级别管制,Spring 提供了疏导策略。
TestContextBootstrapper
定义了用于疏导 TestContext
框架的 SPI。TestContextManager
应用 TestContextBootstrapper
加载以后测试的 TestExecutionListener
实现并构建它治理的 TestContext
。你能够间接应用@BootstrapWith
或作为元注解,为测试类(或测试类层次结构)配置自定义疏导策略。如果没有通过应用 @BootstrapWith
显式配置疏导程序,则依据 @WebAppConfiguration
的存在,应用 DefaultTestContextBootstrapper
或WebTestContextBootstrapper
。
因为 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
属性文件中的 key
为org.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
实现。
为防止必须理解并从新申明所有默认监听器,能够将 @TestExecutionListeners
的mergeMode
属性设置为 MergeMode.MERGE_WITH_DEFAULTS
。MERGE_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
的其余性能。相同,TestExecutionListener
在 ApplicationContext
中不是 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…
微信公众号:
技术交换群: