真正的单元测试通常运行得非常快,因为不需要设置运行时基础设施。然而,对于某些单元测试场景,Spring框架提供了模拟对象和测试支持类。
♠ 单元测试的浅显理解
单元测试(模块测试)是开发者编写的一小段代码,用于检验被测代码的一个很小的、很明确的功能是否正确。通常而言,一个单元测试是用于判断某个特定条件(或者场景)下某个特定函数的行为。例如,你可能把一个很大的值放入一个有序list 中去,然后确认该值出现在list 的尾部。或者,你可能会从字符串中删除匹配某种模式的字符,然后确认字符串确实不再包含这些字符了。
执行单元测试,就是为了证明这段代码的行为和我们期望的一致。其实我们每天都在做单元测试。你写了一个函数,除了极简单的外,总是要执行一下,看看功能是否正常,有时还要想办法输出些数据,如弹出信息窗口什么的,这也是单元测试。
一般单元测试的内容包括:接口测试、数据结构测试、边界条件测试、判断和控制语句的测试。
一、模拟对象
Spring包括许多专门用于mocking的包:
- org.springframework.mock.env
- org.springframework.mock.jndi
- org.springframework.mock.web
- org.springframework.mock.http.server.reactive
注意:spring5 后 org.springframework.mock.web基于Servlet 4.0 API。
org.springframework.mock.env
包含环境和PropertySource抽象的模拟实现,MockEnvironment和MockPropertySource对于为依赖于特定于环境的属性的代码开发容器外测试非常有用。
org.springframework.mock.jndi
包含jndi SPI的实现,您可以使用它为测试套件或独立应用程序设置简单的jndi环境。例如,如果JDBC数据源实例在测试代码中绑定到与javaee容器中相同的JNDI名称,则可以在测试场景中重用应用程序代码和配置而无需修改。
org.springframework.mock.web
包含一组全面的Servlet API模拟对象,这些对象对于测试web上下文、控制器和过滤器非常有用。这些模拟对象是针对Spring的webmvc框架使用的,通常比动态模拟对象(如EasyMock)或替代的Servlet API模拟对象(如Mock对象)更方便使用。
org.springframework.mock.http.server.reactive
包含ServerHttpRequest和ServerHttpResponse的模拟实现,用于WebFlux应用程序。这个org.springframework.mock.web.server包包含一个依赖于这些模拟请求和响应对象的模拟ServerWebExchange。
MockServerHttpRequest和MockServerHttpResponse都是从与特定于服务器的实现相同的抽象基类扩展的,并与它们共享行为。例如,一个mock请求在创建之后是不可变的,但是你可以使用ServerHttpRequest中的mutate()方法来创建一个修改过的实例。
为了使mock响应正确实现write contract并返回一个写完成句柄(即Mono<Void>),默认情况下,它使用一个Flux with cache().then(),它缓冲数据并使其可用于测试中的断言。
WebTestClient构建在模拟请求和响应的基础上,为测试没有HTTP服务器的WebFlux应用程序提供支持。客户机还可以用于运行服务器的端到端测试。
二、单元测试支持类
通用测试工具
org.springframework.test.util包包含几个用于单元测试和集成测试的通用实用程序。
ReflectionTestUtils是基于反射的实用程序方法的集合。您可以在测试场景中使用这些方法,在测试应用程序代码的用例时,需要更改常量值、设置非公共字段、调用非公共setter方法或调用非公共配置或生命周期回调方法:
- ORM框架(如JPA和Hibernate)允许对实体中的属性进行私有或受保护的字段访问,而不是公共setter方法。
- Spring对注解(比如@Autowired、@Inject和@Resource)的支持,这些注解为私有或受保护的字段、setter方法和配置方法提供了依赖注入。
- 对生命周期回调方法使用@PostConstruct和@PreDestroy等注解
AopTestUtils是与AOP相关的实用程序方法的集合。你可以使用这些方法来获得对隐藏在一个或多个Spring代理后面的底层目标对象的引用。例如,如果你使用EasyMock或Mockito这样的库将bean配置为动态模拟,并且mock被包装在Spring代理中,那么您可能需要直接访问底层mock来配置对它的期望并执行验证。
Spring MVC测试工具
org.springframework.test.web包包含ModelAndViewAssert,您可以将其与JUnit、TestNG或任何其他处理Spring MVC ModelAndView对象的单元测试框架结合使用。
三、更多的资源介绍
Junit:面向程序员的Java测试框架。由Spring框架在其测试套件中使用。
TestNG:一个受JUnit启发的测试框架,增加了对注释、测试组、数据驱动测试、分布式测试和其他特性的支持。
Mockito:基于Test-Spy模式的Java模拟库。
EasyMock:通过使用Java的代理机制动态生成接口(和通过类扩展的对象)提供模拟对象。由Spring框架在其测试套件中使用。
JMock:支持使用模拟对象进行Java代码测试驱动开发的库。
DbUnit:JUnit扩展(也可用于Ant和Maven),它针对数据库驱动的项目,并在测试运行期间将数据库置于已知状态。
The Grinder:Java负载测试框架。