Java单元测试之Spock void方法测试
void方法
之前介绍的单元测试中的方法都是带有返回值,可以在then标签中验证返回结果,但是void方法时没有返回值的,就不能再then中验证返回结果。
一般来说无返回值的方法,内部逻辑会修改入参的属性值,比如参数是个对象,那代码里可能会修改它的属性值,虽然没有返回,但还是可以通过校验入参的属性来测试void方法
还有一种更有效的测试方式,就是验证方法内部逻辑和流程是否符合预期,比如:
- 应该走到哪个分支逻辑?
- 是否执行了这一行代码?
- for循环中的代码执行了几次?
- 变量在方法内部的变化情况?
先看一个void方法的业务代码示例:
1 | /** |
这个void方法主要是遍历userVO下面的订单,通过调用汇率接口计算订单的外币金额,然后再赋值给userVO.orderVO.amount,所以他的核心逻辑在for循环里,那么我们的测试重点就是验证for循环里面的逻辑是否符合预期,金额计算是否正确
Spock代码实现
1 | def "SetOrderAmountByExchange"() { |
主要是then标签里的语法: “2 * moneyDAO.getExchangeByCountry(_) >> 0.1413 >> 0.1421”,这行代码表示moneyDAO的getExchangeByCountry()方法会被执行2次,第一次输出的结果是0.1413,第二次输出的接口是0.1421
2 * moneyDAO.getExchangeByCountry(_) >> 0.1413 >> 0.1421
这行代码也可以分开写,比如只写前面的2 * moneyDAO.getExchangeByCountry(_)
2 *
表示方法实际执行的次数, 如果不是2次则不符合预期,单元测试会失败,看你具体的传参,比如在given标签里我们构造的user下面有2个order,订单号分别是1,2,金额分别是10000,1000
在调用void方法时,for循环就会循环2次,所以可以通过这样的写法验证我们调用汇率接口的方法是否执行了,以及执行次数
最后在with()方法里会对入参userVO里的订单金额amount进行校验,因为我们设置的两单订单金额分别是10000和1000,then标签已经对汇率接口的返回结果mock了2个不同的汇率值:0.1413、0.1421,那么转换后的外币金额就是1413和142.1元
也可以将代码修改为1 * moneyDAO.getExchangeByCountry(_) >> 0.1413 >> 0.1421
,再运行测试,会提示相应的错误信息:
报错信息说明实际执行(invoke)了2次
执行几次就写几次,没有执行过就是0 *
,这正是BDD行为驱动开发思想的体现
void+where
如果要结合where测试多分支的void方法时,需要注意一点,因为Spock要求where标签里的表格至少含有两列,如果你的where只是验证入参,也就是只有一列需要验证,那么可以用”_” 表示另外一列值,代码类似下面这样的写法:
1 | where: |
使用“_”表示任意输入或输出
学习大佬文章:https://javakk.com/297.html