Spring Framework 5.0.0.M4中文文档第9,10,11,12章

Part III. 测试

作为 Spring 的开发团队,我们鼓励在开发活动中引入测试驱动开发(TDD,Test-Driveng-Development)的行为,因此本文档接下来将涵盖 Spring 框架对集成测试的支持(以及 Spring 下单元测试的最佳实践)。

Spring 开发团队发现对控制反转(IoC)的正确运用可以使针对代码编写单元测试与集成测试变得更为容易(setter方法的存在,以及类里面恰当的构造器,使得测试代码在无需类似服务工厂等辅助工具的前提下,也能够方便地对各个类进行调用)。我们希望通过整整一章对 Spring 框架下测试相关主题的讲解,让读者也能对我们的以上发现表示赞同。

9. Spring 框架下的测试

测试乃企业级软件开发的重要组成部分之一。本章专注于讲解采用 IoC 原则进行编码而给单元测试带来的好处,以及 Spring 框架对集成测试的支持如何为测试带来帮助。(对企业开发中如何进行代码测试的详尽讨论不在本文档范围之内)

10. 单元测试

比起传统的 Java EE 开发方式,依赖注入可以弱化你的代码对容器的依赖。在基于 Junit 或 TestNG 的测试代码中,无需依赖于 Spring 或其他容器,你只需通过 new 操作符,便可以创建出组成你的应用程序的各种 POJO 对象。而通过 mock 对象(以及其它各种测试技术的综合运用),你可以将被测试的代码单独隔离开来进行测试。如果你在进行架构设计时遵循了 Spring 所推荐的模式,那么由此带来的诸如清晰的分层、组件化等等优点也会使你更容易地对你的代码进行单元测试。例如,通过 mock DAO 层或 Repositry 接口的实现,针对服务层对象的单元测试代码并不需要真正地访问持久层的数据。

真正的单元测试代码运行的非常快,因为并不需要一整套的运行时架构去支持测试的运转。所以在开发中强调真正的单元测试必须成为编码方法论中的一部分将会极大地提高你的生产力。

也许没有这一节内容的帮助你也能写出高效的针对 IoC 应用的单元测试,但是以下将要提到的 Spring 所提供的 mock 对象和测试支持类,在一些特定的场景中会对单元测试很有帮助。

10.1 Mock 对象

10.1.1 环境

org.springframework.mock.env 包含了对抽象 Environment 和 PropertySource 的 Mock 实现(参考 Section 3.13.1 1Bean的定义文件 和 Section 3.13.3 PropertySource抽象)。MockEnvironment 和 MockPropertySource 对于编写针对依赖于环境相关属性的代码的,与容器无关的测试用例很有帮助。

10.1.2 JNDI

org.springframework.mock.jndi 包含了 JNDI SPI 的实现。这一实现可以让你为你的测试套件或独立应用配置起一个简单的 JNDI 环境。例如,如果测试代码和 Java EE 容器的 JDBC DataSource都绑定到同一个 JNDI 名字上,你就可以在测试中直接复用应用程序的代码和配置而不需做任何改动。

10.1.3 Servlet API

The org.springframework.mock.web package contains a comprehensive set of Servlet API mock objects, which are useful for testing web contexts, controllers, and filters. These mock objects are targeted at usage with Spring’s Web MVC framework and are generally more convenient to use than dynamic mock objects such as EasyMock or alternative Servlet API mock objects such as MockObjects. Since Spring Framework 4.0, the set of mocks in the org.springframework.mock.webpackage is based on the Servlet 3.0 API.

For thorough integration testing of your Spring MVC and REST Controllers in conjunction with your WebApplicationContext configuration for Spring MVC, see theSpring MVC Test Framework.

org.springframework.mock.web 包含了十分全面的 Servlet API mock 对象。这些对象在测试web 上下文,Controller 和 Filter 的时候很有用。由于这些 mock 对象是有针对性地为了与 Spring 的 Web MVC 框架共同使用而编写的,因此相比起诸如 EasyMock 这种动态mock 对象或 MockObjects 这种替代性的 Servlet API mock 对象,使用起来要更为方便。

假如是要把 Spring MVC 和 REST Controller与 WebApplicationContext 配置结合起来进行一番彻底的集成测试,请使用 Spring MVC 测试框架 。

10.2 单元测试支持类

10.2.1 通用支持工具

org.springframework.test.util 包含了一些供单元测试和集成测试中使用的通用工具。

ReflectionTestUtils 是一组基于反射的方法集合。在测试包含如下一些测试用例的应用时,开发人员可以使用这些工具方法应对诸如更改一个常量的值,赋值一个非公有字段,调用一个非公有setter方法,或调用一个非公有的 配置 或 生命周期 回调方法等测试场景:

  • 诸如 JPA 和 Hibernate 等广泛采用private或protected访问方式而public setter方法来访问domain entity属性的ORM(Object-Relational Mapping)框架
  • @Autowired,@Inject和@Resource等用于对private或protected字段,setter 方法和配置方法进行依赖注入的 Spring 注解。
  • @PostConstruct和@PreDestroy等用在生命周期回调方法上的注解。

AopTestUtils是一组 AOP 相关工具方法的集合。这些方法可以用于帮助获取隐藏于一重或多重 Spring 代理背后目标对象的引用。举个栗子,你使用 EasyMock 或 Mockito mock 了一个被包装在 Spring 代理之中的 bean,这时你可能需要对这个 mock 进行直接的访问,从而能够配置对此 mock 的期望行为并在稍后执行验证。关于 Spring 提供的核心 AOP 工具,请参考AopUtils和AopProxyUtils这两个类。

10.2.2 Spring MVC

The org.springframework.test.web package contains ModelAndViewAssert, which you can use in combination with JUnit, TestNG, or any other testing framework for unit tests dealing with Spring MVC ModelAndView objects.

org.springframework.test.web包含了ModelAndViewAssert类。你可以在用 Junit,TestNG 或任何测试框架编写的单元测试中使用这个类来帮助你跟 Spring MVC 框架的ModelAndView对象进行互动。

注:如果想要像测试 POJO 一样来测试你的 Spring MVC Controller,你可以将ModelAndViewAssert与MockHttpServletRequest、MockHttpSession等来自 Servlet API mocks 的 Mock 类结合使用。而假如是要把 Spring MVC 和 REST Controller 与WebApplicationContext配置结合起来进行一番彻底的集成测试,请使用Spring MVC 测试框架。

11. 集成测试

11.1 概述

能够在不需要部署到应用服务器或连接到其它企业基础服务的前提下做一些集成测试是很重要的。这将使你能够测试以下内容:

  • Spring IoC容器上下文的正确装配。

  • 使用JDBC或其它ORM工具访问数据。这将包括SQL语句、Hibernate查询和JPA实体映射的正确性等等这些内容。

Spring Framework在spring-test模块中为集成测试提供了强有力的支持。该Jar包的实际名字可能会包含发布版本号而且可能是org.springframework.test这样长的形式,这取决于你是从哪获得的(请参阅section on Dependency Management中的解释)。这个库包括了org.springframework.test包,其中包含了使用Spring容器进行集成测试的重要的类。这个测试不信赖于应用服务器和其它的发布环境。这些测试会比单元测试稍慢但比同类型的Selenium测试或信赖于发布到应用服务器的远程测试要快得多。

在Spring2.5及之后的版本,单元和集成测试支持是以注解驱动Spring TestContext框架这样的形式提供的。TestContext框架对实际使用的测试框架是不可知的的,因此可以使用包括 JUnit, TestNG等等许多测试手段。

11.2 集成测试的目标

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

  • 管理各个测试执行之间的Spring IoC容器缓存
  • 提供测试配置实例的依赖注入
  • 提供适合集成测试的事务管理
  • 提供辅助开发人员编写集成测试的具备Spring特性的基础类

下面几节将解释每个目标并提供实现和配置详情的链接。

11.2.1 上下文管理和缓存

Spring TestContex框架对Spring ApplicationContext和WebApplicationContext提供一致性加载并对它们进行缓存。对加载的上下文进行缓存提供支持是很重要的,因为启动时间是个问题——不是因为Spring自己的开销,而是被Spring容器初始化的对象需要时间去初始化。比如,一个拥有50到100个Hibernate映射文件的项目可能花费10到20秒的时间去载这些映射文件,在运行每一个测试工具中的测试用例之前都会引发开销并导致总体测试运行变缓慢,降低开发效率。

测试类通常声明一批XML的资源路径或者Groovy的配置元数据——通常在类路径中——或者是一批用于配置应用程序的注解类。这些路径或者类跟在web.xml或者其它用于生产部署的配置文件中指定的是一样的。

通常,一旦被加载过一次,ApplicationContext就将被用于每个测试中。因此启动开销在一次测试集中将只会引发一次,随后执行的测试将会快得多。在这里,“测试集”的意思是在同一个JVM的所有测试——比如说,对给定项目或者模块的一次Ant、Maven或者Gradle构建运行的所有测试。在不太可能的情况下,一个测试会破坏应用上下文并引起重新加载——比如,修改一个bean定义或者应用程序对象的状态——TestContex框架将被设置为在开始下个测试之前重新加载配置并重建应用上下文。

参见Section 11.5.4, “Context management”和TestContext框架的the section called “Context caching”一节。

11.2.2 测试配置的信赖注入

当TestContext框架加载你的应用程序上下文的时候,它将通过信赖注入有选择性地配置测试实例。这为使用你的应用程序上下文中的预配置bean来建立测试配置提供了一个很方便的机制。这里有一个很大的便处就是你可以在不同的测试场景中重复使用应用程序上下文(比如,配置基于Spring管理的对象图、事务代理、数据源等等),这样省去了为每个测试用例建立复杂的测试配置的必要。

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

  • Spring配置:总的来说,就是与HibernateTitleRepository配置有关的一切是否正确和存在?
  • Hibernate映射文件:是否所有映射都正确,并且延迟加载的设置是否准备就绪?
  • HibernateTitleRepository的逻辑:此类中的配置实例是否与预期一致?

查看使用TestContext框架进行测试配置的信赖注入。

11.2.3 事务管理

测试中访问一个真实数据库的一个常见的问题是在持久层存储状态付出的努力。即使你使用开发环境的数据库,改变相应的状态也会影响将来的测试。并且,许多操作——插入或者改变持久层数据——也不能在事务之外执行(或者验证)。

TestContext框架解决了这个问题。默认行为下,这个框架将为每个测试创建并回滚一个事务。你只需简单的假定事务是存在的并写你的代码即可。如果你调用事务代理对象,他们也会根据它们配置的语义正确执行。而且,如果一个测试方法在运行相应事务时删除了选定表中的内容,事务默认情况下会进行回滚,数据库会回到测试执行前的那个状态。事务通过定义在应用程序上下文中的PlatformTransactionManager bean来得到支持。

如果你需要提交事务——通常不会这样做,但有时当你想用一个特定的测试来填充或者修改数据库时也会显得有用——TestContext框架将根据@Commit注解的指示对事务进行提交而不是回滚。

查看使用TestContext框架进行事务管理。

11.2.4 集成测试的支持类

Spring TestContext框架提供了一些支持来简化集成测试的编写。这些基础类为测试框架提供了定义良好的钩子,还有一些便利的实例变量和方法,使你能够访问:

  • ApplicationContext,用于从整体上来进行显示的bean查找或者测试上下文的状态。
  • JdbcTemplate,用于执行SQL语句来查询数据库。这些的查询可用于确认执行数据库相关的应用程序代码前后数据库的状态,并且Spring保证这些查询与应用程序代码在同一个事务作用域中执行。如果需要与ORM工具协同使用,请确保避免误报。

还有,你可能想用特定于你的项目的实例和方法来创建你自己自定义的,应用程序范围的超类。

查看TestContext框架的支持类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值