如何在Spock框架中正确验证Mock方法调用且避免测试失败?
Spock Mock验证与存根冲突问题解决
问题根源:当你在then块单独添加1 * supp.get()这类交互验证时,它会覆盖given块中定义的存根逻辑,导致get()调用返回默认的null,进而触发断言失败。
正确解决方法
方法一:验证与存根合并到then块(推荐)
在then块中同时声明调用次数验证和返回值逻辑,既保证验证生效,又保留存根的返回值:
package com.workato.agent.smb import spock.lang.Specification import java.util.function.Supplier class SomeSpec extends Specification { def "test"() { given: def resource = "ABC" def supp = Mock(Supplier) when: def res = supp.get() then: // 同时验证调用次数并指定返回值 1 * supp.get() >> resource res == resource } }
方法二:在given块提前定义验证与存根
如果更习惯在前置阶段定义Mock行为,可以直接在given块中同时声明调用次数和返回值,then块仅做结果断言:
package com.workato.agent.smb import spock.lang.Specification import java.util.function.Supplier class SomeSpec extends Specification { def "test"() { given: def resource = "ABC" def supp = Mock(Supplier) // 提前定义调用次数与返回值逻辑 1 * supp.get() >> resource when: def res = supp.get() then: res == resource } }
复杂存根逻辑的适配
如果你的存根需要依赖参数或执行复杂逻辑,直接把闭包放到>>后即可,不影响验证逻辑:
// 闭包形式的存根示例 1 * supp.get() >> { args -> // 这里可以编写复杂逻辑,比如处理参数、动态计算返回值 resource }
原理说明
Spock的Mock交互声明是按匹配优先级生效的,单独的1 * supp.get()会成为优先匹配的规则,且未指定返回值时会返回默认的null。将验证与存根合并后,既能确保调用次数被校验,又能保留自定义的返回值逻辑。
内容的提问来源于stack exchange,提问作者diziaq
相关产品推荐
相关产品推荐

