15.2 集成测试的目标

Spring对集成测试的支持具有以下主要目标:

  • 在测试执行期间管理Spring IoC容器的缓存。
  • 测试固件(test fixture)实例提供依赖注入。
  • 提供适合集成测试的事务管理。
  • 提供Spring指定的基类以帮助开发者编写集成测试。

接下来的几节将描述每一个目标,并提供到实现和配置细节的链接。

15.2.1 上下文管理及缓存

Spring TestContext框架提供一致的方式加载Spring的ApplicationContext和WebApplicationContext,并缓存这些上下文。能够对已加载的上下文进行缓存是很重要的,因为启动时间可能是一个问题,这不是由于Spring本身的开销,而是由于Spring容器实例化的对象需要时间来完成实例化。例如,一个具有50到100个Hibernate映射文件的项目可能需要10到20秒来加载映射文件,还要忍受每个测试固件中的每一个测试执行前的损耗,这些损耗拖慢了整个测试的运行,降低了开发者的生产力。

测试类通常要么声明一个XML配置元数据的资源地址(经常在类路径中)的数组,要么声明一个用来配置程序的注解类的数组。这些地址或类与生产环境的web.xml或其他部署配置文件中指定的相同或类似。

默认情况下,配置好的ApplicationContext一旦加载,将在每个测试中重用。因此,每个测试套件只需忍受一次准备期的损耗,后续的测试会执行的更快。在当前背景下,术语测试套件指在同一个JVM下运行的所有测试。例如,为构建一个特定项目或模块由Ant、Maven或Gradle执行的全部测试。在不太可能的情况下,一个测试会破坏应用程序上下文并且需要重新加载,例如,修改了bean的定义或程序对象的状态,可以配置TestContext框架在执行下一个测试前重新加载配置并重新构建应用程序上下文。

参阅15.5.3 上下文管理及上下文缓存小节。

15.2.2 测试固件的依赖注入

当TestContext框架加载了应用上下文,它能够通过依赖注入有选择地配置测试类的实例。这为使用应用上下文中预配置的bean来设置测试固件提供了一个方便的机制。这里一个很大的好处是,可以在各种测试场景中重用应用上下文(例如,配置Spring管理的对象图、事务代理、数据源等),从而避免了为单一测试用例重复设置复杂的测试固件。

举个例子,考虑这样一个场景:我们有一个HibernateTitleRepository类,它针对Title领域实体实现了数据访问逻辑。我们想编写集成测试测试以下方面:

  • Spring的配置:基本上就是与HibernateTitleRepository的配置有关的一切是否正确且呈现?
  • Hibernate映射文件的配置:是否一切正确映射?以及设置的延迟加载是否正确?
  • HibernateTitleRepository的逻辑:这个类已配置的实例是否如预期般执行?

参阅使用TestContext框架依赖注入测试固件

15.2.3 事务管理

在访问真正数据库的测试中一个常见的问题是测试对持久存储的状态的影响。即使正在使用开发环境数据库,状态的改变也可能对未来的测试产生影响。此外,许多操作(如插入或修改持久数据)不能在事务外执行。

TestContext框架解决了这一问题。默认情况下,框架会为每一个测试创建一个事务并回滚,您只需编写假定事务存在的代码。如果在测试中调用了事务代理对象,它们会根据其配置好的事务语义正确运行。另外,如果在测试所管理的事务下,一个测试方法删除了选定表的内容,默认情况下,事务会回滚,数据库会恢复到测试执行之前的状态。事务支持是通过定义在测试的应用上下文中PlatformTransactionManager类的bean提供给测试的。

如果想提交一个事务——不常见,但当您偶尔希望一个特殊的测试填充或修改数据库时有用——可以通过@Commit注解告诉TestContext框架让事务提交而不是回滚。

参阅使用TestContext框架管理事务

15.2.4 支持集成测试的类

Spring的TestContext框架提供了几个抽象类,它们简化了编写集成测试的过程。这些测试基类提供了在测试框架中使用的定义良好的钩子,以及方便的实例变量和方法,它们使您能够访问:

  • ApplicationContext,用于执行显式的bean查找或者测试作为一个整体的上下文的状态。
  • JdbcTemplate,用于执行SQL语句来查询数据库。这样的查询可以用来确认数据库在与数据库相关的程序代码执行之前及之后的状态,而且Spring确保这些查询在程序代码同一个事务的范围内执行。当与ORM工具一起使用时,一定要避免误报。

此外,您可能想创建自定义的、带有实例变量和方法的应用范围内的、项目特有的超类。

参阅支持TestContext框架的类