码总是里充斥着各种when(),anyXXX(),return()之类啰嗦的关键词,加上java本身就是一个啰嗦的强类型的语言,这让写单测和读单测成为了一种体力活。
其次是单测数据,大部分测试都要提供数据,比如“当输入a的时候应该返回b”,如果只有一组数据那么没什么问题,但是当需要测试很多边界条件,需要多组数据的时候就会比较纠结。
用jUnit或者testng的dataprovider可以实现这个需求,但是无论是通过xml定义还是通过函数返回数据,都非常不方便。
最后,因为这些框架都只是一些独立的函数,没有告诉你“应该怎么写单测”,所以不同的人最终写出来的单测也是五花八门:
- 有不用assert而是用system.out.println的
- 有单测一个函数写了好几百行的
- 有直接把单测当成main函数写的
最终,团队要接受“虽然确实写了单测,然而这并没有什么卵用”的结果。
3.2.2.为什么使用spock
还是刚才的例子,如果用spock写的话:
def "isUserEnabled should return true only if user status is enabled"() {
given:
UserInfo userInfo = new UserInfo(
status: actualUserStatus
);
userDao.getUserInfo(_) >> userInfo;
expect:
userService.isUserEnabled(1l) == expectedEnabled;
where:
actualUserStatus | expectedEnabled
UserInfo.ENABLED | true
UserInfo.INIT | false
UserInfo.CLOSED | false
}
这段代码实际是3个测试:当getUserInfo返回的用户状态分别为ENABLED、INIT和CLOSED时,验证各自isUserEnabled函数的返回是否符合期待。
我对于spock框架最直接的感受:
- spock框架使用标签分隔单元测试中不同的代码,更加规范,也符合实际写单元测试的思路
- 代码写起来更简洁、优雅、易于理解
- 由于使用groovy语言,所以也可以享受到脚本语言带来的便利
- 底层基于jUnit,不需要额外的运行框架
- 已经发布了1.0版本,基本没有比较严重的bug
3.2.3.为什么不用spock
用了一段时间的spock后,我也总结了几个不用spock的理由:
- 框架相对比较新,IDE的支持(尤其是eclipse)不如其它成熟的框架
- groovy语言本身的compiler更新比较快,偶尔有坑(版本不兼容等)
- 需要了解groovy语言
- 与其它java的测试框架风格相差比较大,需要适应
当然,这些理由比起spock提供的易于开发和维护的单元测试代码来说,都是可以忽略的。
4.使用Spock
写到这里,还是要聚焦一下这篇文章要讨论的问题:如何用spock框架编写单元测试,在此之前再强调一下:
- 单元测试不一定非要使用spock,但是其它框架写出的单元测试代码远没有用spock框架优雅。
- spock框架并不只能写单元测试,它也可以写集成测试,甚至性能测试,但是后两者spock相对于其它框架来说没有什么优势。
4.1.关于开发环境
在使用spock框架时,我比较推荐的ide是IDEA,推荐的构建工具是gradle。
就算不使用spock框架,IDEA的顺手程度也比eclipse好太多,对新技术的响应速度快,也没有那么多莫名其妙的严重bug,社区版免费但主要功能都有,没有什么理由不试用一下。
而gradle相对于maven来说配置简化了很多,可定制的功能也更强,与其迷失在maven复杂的xml和一层套一层的依赖关系中,我宁愿把时间做一些更有意思的事情。
由于IDE基本可以自由选择,但构建工具大部分是由团队决定的,而maven现在还是处于构建工具的领导地位,所以这篇文章里的步骤都是基于IDEA+maven,当前的IDEA已经支持spock,不需要做什么特殊配置。
- 如果你的团队应用了gradle,spock官网中对于gradle如何配置说的比较完整,可以直接参考官网。
- 如果你执迷不悟非要使用eclipse,我在eclipse下也跑通了整个流程。需要安装最新的groovy-eclipse插件和附加包(安装时选择groovy2.4版以上的compiler),地址:https://github.com/groovy/groovy-eclipse/wiki
4.2.hello spock
前面做了那么多铺垫,终于到了真正编写一个hello world的时候。
到这里,我假设你是一位java开发者,并且已经了解基本的IDE及构建工具的使用。
- 创建一个空白项目:hello_spock,选择maven工程。
- 在pom.xml中增加依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>hello</groupId>
<artifactId>hello_spock</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!-- Mandatory dependencies for using Spock -->
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>1.0-groovy-2.4</version>
<scope>test</scope>
</dependency>
<!-- Optional dependencies for using Spock -->
<dependency> <!-- use a specific Groovy version rather than the one specified by spock-core -->
<g