Spring Testing

来源:互联网 发布:type c数据线线序 编辑:程序博客网 时间:2024/06/14 17:08

单位测试

依赖注入应该使您的代码在容器上的依赖性要低于传统的Java EE开发。构成应用程序的POJO应该在JUnit或TestNG测试中可测试,使用new操作符简单地实例化对象,而不使用Spring或任何其他容器。您可以使用模拟对象(结合其他有价值的测试技术)来隔离测试代码。如果您遵循Spring的架构建议,您的代码库的干净分层和组件化将有助于简化单元测试。例如,您可以通过存根或模拟DAO或Repository接口来测试服务层对象,而无需在运行单元测试时访问持久性数据。

真正的单元测试通常运行得非常快,因为没有运行时基础架构来设置。强调真正的单元测试作为开发方法的一部分将提高您的生产力。您可能不需要测试章节的这一部分来帮助您为基于IoC的应用程序编写有效的单元测试。但是,对于某些单元测试场景,Spring Framework提供了以下模拟对象和测试支持类。

模拟对象

环境

org.springframework.mock.env包包含了EnvironmentPropertySource抽象的模拟实现(见“Bean定义配置文件”和“PropertySource抽象”)。MockEnvironmentMockPropertySource可用于开发针对依赖环境特性的代码的容器外测试。

JNDI

org.springframework.mock.jndi包中包含一个JNDI SPI的实现,您可以使用它为测试套件或独立应用程序设置简单的JNDI环境。例如,JDBCDataSources在测试代码中绑定到与Java EE容器中相同的JNDI名称,您可以在测试场景中重用应用程序代码和配置,而无需修改。

Servlet API

org.springframework.mock.web软件包包含一套全面的Servlet API模拟对象,可用于测试Web上下文,控制器和过滤器。这些mock对象的目标是使用Spring的Web MVC框架,并且通常比动态模拟对象(如EasyMock)或替代的Servlet API模拟对象(如MockObjects)更方便使用。从Spring Framework 4.0起,org.springframework.mock.web包中的mocks集合基于Servlet 3.0 API。

有关Spring MVC和REST控制器的完整集成测试以及Spring MVC的WebApplicationContext配置,请参阅Spring MVC测试框架。

Portlet API

org.springframework.mock.web.portlet包包含一组Portlet API模拟对象,目标是使用Spring的Portlet MVC框架。

单元测试支持类

通用测试工具

org.springframework.test.util包包含用于单元和集成测试的几个通用实用工具。

ReflectionTestUtils是基于反射的实用方法的集合。开发人员使用这些方法在以下测试场景中:需要改变常量的值,设置非public字段,调用非publicsetter方法,或者在测试涉及use cases的应用程序代码时调用非public配置或生命周期回调方法,如下所示。

  • ORM框架,如JPA和Hibernate,它允许privateprotected的字段访问,而不是域实体中的属性的publicsetter方法。
  • Spring支持@Autowired@Inject@Resource等注释,为privateprotected的字段提供依赖注入,setter方法和配置方法。
  • 使用注释(如@PostConstruct@PreDestroy)来进行生命周期回调方法。

AopTestUtils是与AOP相关的实用方法的集合。这些方法可用于获取对一个或多个Spring代理隐藏的底层目标对象的引用。例如,如果您使用类似EasyMock或Mockito的库将Bean配置为动态模拟,
并将模拟包装在Spring代理中,您可能需要直接访问底层模拟,才能对其进行预期并执行验证。对于Spring的核心AOP实用程序,请参阅AopUtilsAopProxyUtils

Spring MVC

org.springframework.test.web包包含ModelAndViewAssert,您可以结合使用JUnit,TestNG或任何其他测试框架来处理Spring MVC ModelAndView对象的单元测试。

要将Spring MVC控制器单元测试为POJO,请使用ModelAndViewAssert与Spring的Servlet API mocks中的MockHttpServletRequestMockHttpSession等组合。为了将Spring MVC和REST控制器与Spring MVC的WebApplicationContext配置结合进行彻底集成测试,请改用Spring MVC测试框架。

集成测试

概貌

能够执行一些集成测试,而不需要部署到应用服务器或连接到其他企业基础架构,这一点非常重要。这将使您能够测试以下内容:

  • 您的Spring IoC容器上下文的正确连接。
  • 使用JDBC或ORM工具进行数据访问。这将包括SQL语句,Hibernate查询,JPA实体映射等的正确性。

Spring框架为spring-test模块中的集成测试提供了一流的支持。实际的JAR文件的名称可能包括发行版本,也可能在longorg.springframework.test表单中,具体取决于您从哪里获取(参见“依赖关系管理”一节进行说明)。该库包括
org.springframework.test包,它包含用于使用Spring容器进行集成测试的有价值的类。此测试不依赖于应用程序服务器或其他部署环境。这些测试比单元测试运行速度更慢,但比依赖于部署到应用服务器的等效Selenium测试或远程测试快得多。

在Spring 2.5及更高版本中,单元和集成测试支持以注解驱动的Spring TestContext框架的形式提供。TestContext框架与使用中的实际测试框架无关,因此允许在各种环境中进行测试,包括JUnit,TestNG等。

集成测试目标

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

  • 管理Spring IoC容器缓存之间的测试执行。
  • 提供测试夹具实例的依赖注入。
  • 提供适合于集成测试的事务管理。
  • 提供Spring特定的基类,帮助开发人员编写集成测试。

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

上下文管理和缓存

Spring TestContext框架提供了Spring ApplicationContextsWebApplicationContexts的一致加载以及这些上下文的缓存。支持缓存加载的上下文很重要,因为启动时间可能会成为问题 – 不是因为Spring本身的开销,而是由于Spring容器实例化的对象需要时间来实例化。例如,具有50到100个Hibernate映射文件的项目可能需要10到20秒才能加载映射文件,并且在每个测试夹具中运行每个测试之前产生该成本导致整体测试运行较慢,从而降低开发人员的生产力。

测试类通常为XML或Groovy配置元数据(通常在类路径中)声明资源位置数组,或者用于配置应用程序的注解类数组。这些位置或类与web.xml或生产部署的其他配置文件中指定的位置或类相同或相似。

默认情况下,一旦加载,配置的ApplicationContext将重新用于每个测试。因此,每个测试套件的安装成本仅发生一次,后续的测试执行速度要快得多。在这种情况下,术语测试套件意味着所有测试都运行在相同的JVM中 - 例如,所有测试都从给定项目或模块的Ant,Maven或Gradle构建运行。在不太可能的情况下,测试会破坏应用程序上下文并需要重新加载 – 例如,通过修改bean定义或应用程序对象的状态 - 可以配置TestContext框架以在执行下一个测试之前重新加载配置并重新构建应用程序上下文。

参见第“上下文管理”和TestContext框架的“上下文缓存”一节。

测试夹具的依赖注入

当TestContext框架加载您的应用程序上下文时,它可以选择通过依赖注入来配置测试类的实例。这提供了一种方便的机制,可以使用来自应用程序上下文的预配置的bean设置测试夹具。这里的一大优点是您可以在各种测试场景(例如,配置Spring管理的对象图,事务代理,DataSources等)中重用应用程序上下文,从而避免了复杂的测试夹具对于各个测试用例的复制。

例如,考虑我们有一个类HibernateTitleRepository,它为Title域实体实现数据访问逻辑的场景。我们想要编写测试以下几个方面的集成测试:

  • Spring配置:基本上是与HibernateTitleRepository bean的配置有关的一切是否正确?
  • Hibernate映射文件配置:是否正确映射了所有映射,并且是正确的延迟加载设置吗?
  • HibernateTitleRepository的逻辑:此类的配置实例是否按预期方式执行?

请参阅TestContext框架的依赖注入测试夹具。

事务管理

访问真实数据库的测试中的一个常见问题是它们对持久性存储的状态的影响。即使在使用开发数据库时,状态的更改可能会影响未来的测试。此外,许多操作(例如插入或修改持久性数据)不能在事务之外执行(或验证)。

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

如果你想要一个事务提交 – 不常见的,但是当您想要特定的测试来填充或修改数据库时,偶尔会很有用 – 可以指示TestContext框架通过@Commit注释导致事务提交而不是回滚。

请参阅TestContext framework的事务管理。

集成测试支持类

Spring TestContext框架提供了几个抽象支持类,简化了集成测试的编写。这些基础测试类为测试框架提供了明确的钩子,以及方便的实例变量和方法,使您能够访问:

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

此外,您可能希望创建自己的自定义应用程序范围的超类与实例变量和特定于您的项目的方法。

请参阅TestContext框架的支持类。

JDBC测试支持

org.springframework.test.jdbc包包含JdbcTestUtils,它是用于简化标准数据库测试场景的JDBC相关实用程序函数的集合。具体来说,JdbcTestUtils提供了以下静态实用程序方法。

  • countRowsInTable(..): 计算给定表中的行数
  • countRowsInTableWhere(..): 使用提供的WHERE子句来计算给定表中的行数
  • deleteFromTables(..): 从指定的表中删除所有行
  • deleteFromTableWhere(..): 使用提供的WHERE子句从给定的表中删除行
  • dropTables(..): 删除指定的表

请注意,AbstractTransactionalJUnit4SpringContextTestsAbstractTransactionalTestNGSpringContextTests提供了在JdbcTestUtils中委派给上述方法的便利方法。

spring-jdbc模块支持配置和启动可与数据库交互的集成测试中使用的嵌入式数据库。
有关详细信息,请参见“嵌入式数据库支持”和“使用嵌入式数据库测试数据访问逻辑”

注解

Spring测试注解

Spring框架提供了以下一组特定于Spring的注释,您可以在单元中使用该注解,并结合TestContext框架进行集成测试。有关更多信息,请参阅相应的javadocs,包括默认属性值,属性别名等。

……

参考链接: spring testing