Spock测试中Groovy的it变量及save方法入参代码块含义咨询
Spock单元测试Groovy代码问题解答
你遇到的示例代码如下:
1 * subject.statusRepository.save({ it.Id == request.Id it.location == location it.team == statusExisting.getTeam() it.statusEnum == StatusEnum.Status.W })
关于it变量的含义与作用
it是Groovy语言为单参数闭包提供的隐式默认参数名,不需要开发者手动声明:只要定义的闭包只接收1个入参,Groovy就会自动把传入的参数绑定到it变量上,可以直接在闭包内部使用。
放到这段Spock测试的场景里,it指代的就是代码运行时statusRepository.save()方法实际接收到的入参,也就是待持久化的状态实体对象。你在闭包里写的所有it.xxx == 预期值的逻辑,本质是在对save方法的入参做字段级校验。
关于传入save方法的大括号代码块语法说明
这个结构不是JSON,是Groovy闭包(Closure),属于Groovy原生支持的一等公民语法,本质是一个可传递的匿名代码块,可以作为参数传给方法、持有上下文变量、被调用执行。
你觉得它形似JSON,是两个语法特性带来的视觉错觉:
- Groovy语法规定,如果闭包是方法调用的最后一个参数,可以把闭包从方法括号里挪到括号外面书写,视觉上看起来像是直接跟在方法后面的独立块;
- 这个闭包内部没有复杂逻辑,全是属性相等判断的语句,视觉上和JSON的键值对结构有相似性,但本质上是逐行执行的布尔判断逻辑,没有JSON的键值映射语义。
在这段Spock代码里,这个闭包的作用是自定义参数匹配器:开头的1 *是Spock的交互断言,表示save方法必须被恰好调用1次,这类断言默认会对参数做全值相等匹配;当你不需要校验整个入参对象完全相等,只需要校验入参的部分字段符合预期、或者满足自定义规则时,就可以传入一个返回布尔值的闭包作为匹配规则。Spock会把save方法被调用时的实际入参传给这个闭包执行,只要闭包最终返回true,就判定参数符合断言要求;返回false则直接判定交互断言失败。
这里提一个新手常踩的坑:Groovy的闭包和方法一样,默认把最后一行代码的执行结果作为返回值,所以这段代码里闭包的返回值实际是最后一行it.statusEnum == StatusEnum.Status.W的布尔结果,前面几行判断的结果如果不做特殊处理不会影响最终返回值——如果要让所有字段都参与校验,要么把所有判断条件用&&连接,要么在每一行判断前加assert关键字,否则前面字段不匹配也会被判定为参数校验通过。
内容的提问来源于stack exchange,提问作者Toni26
相关产品推荐
相关产品推荐

