一、Spock是什么?
- Spock是一个可以应用于java或groovy的测试框架
- 在编写单元测试过程中去掉依赖的类/对象/资源,专注测试类本身,实现解耦
- Spock测试框架基于Groovy并吸收了Junit、TestNG、Mockito等测试框架的优点
- Spock编写的单元测试层次清晰,优雅,代码量少,可读性好
二、Spock+Groovy让我们的测试代码更轻
- groovy是一种非常类似java的语言,但是语法更加轻,每句代码结尾不用分号结束,也不需要用public修饰,因为pubilc是默认的。
- 在spock中mock对象非常容易,只需要使用Mock(class)
- Groovy可以使用字符串文本来命名方法,这个特性使测试方法更加容易被阅读和理解。
- expect可以看做精简版的when+then
- “>>” 表示模拟对象的返回值
- “>>>” 表示同一方法多次按顺序调用返回不同值
- 下划线“_”表示匹配所有的输入值
- Spock不使用Assert来校验结果,then声明后面的表达式result=="1"就相当于Junit中的Assert.assertTrue(result.equals("1"))
- n * . 表示期望对对象的方法n次调用
三、spock的与其他框架的对比
1、Spock强制使用一套清晰的测试结构
使用Spock原因是会让你感觉层级分明,相对于其他框架来说代码具有更高的可读性,而JUnit测试缺乏正式的语义,在JUnit测试中,arrange-act-assert模式是隐含的很容易被忽略,例如一名java开发人员可将JUnit测试写成如下:
当arrange-act-assert模式结构被破坏了,代码可阅读性变差,当内容较长,逻辑复杂,这时单测的维护成本就变的很大,而Spock除了使用基本的given-when-then,还可以使用其他的代码块来保证测试的结构完整性。
开发维护人员仅仅通过阅读对应的代码块的名字即可知道这个测试是做什么的,清晰明了。
2、参数化测试
JUnit和Mockito对于参数化的支持非常有限而且很受限制,JUnit测试很显然不符合DRY原则(Don't repeat yourself,不要重复自己),有太多的相同代码, 而Spock提供数据表格正好能解决这个问题, spock能以直观的方式编写参数化,而且代码不需要重复,将数据和描述以表格的形式放在一起。通过以上代码可以看到,这里讲三个JUnit的测试合并在一个单独的spock测试里,不需要写重复代码, 测试逻辑只要写一次,所有的输入和输出都集中在一个地方,可阅读性高,参数名称在表格头部清晰可见。
3、开箱即用
Groovy自动提供一个构造函数,构造函数接受一个名称-值对与类的属性相对应,是Groovy开箱即用的功能— 用于类中定义的任何属性,Groovy 允许将存储了大量值的映射传给构造函数,不用初始化对象的每个属性,减轻代码。
新建一个类song:
可添加下面这个代码:
在JUnit只能一个个的set值,比较繁琐。
4、关于重载
在实际开发项目中,少不了用重载,在JUnit中测试重载需要写大量的重复代码,非常繁琐复杂,而在Spock中使用*匹配器,如上用restTemplate.exchange(*),即可测试所有的重载方法,简洁优雅。
5、断言异常
Spock还为我们提供了一种表达方式来检查异常情况。在JUnit中,我们的一些选项可能会使用try-catch块,在我们测试的顶部声明,或者使用第三方库。 Spock的原生断言提供了一种处理exception情况的方法:
在这里,我们不需要引入额外的库。另一个优点是thrown()方法将断言异常的类型,但不会暂停执行测试。
6、mock和stubbing
通过使用mock和stub,可以让mock对象进行交互,获得期望的返回值,这在JUnit和mockito中是很难实现的,而在Spock仅用几行代码就可以优雅实现了。