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

微信公众号:

技术交换群: