Spock交互验证失效报Too few Invocations 调用次数不足错误
问题成因
测试不通过是三个核心问题导致的:
- 你写的
MyClass里getName、toUpperCase全是静态方法。静态方法是类级别的,调用绑定在类上不走实例代理:你在getName里调toUpperCase本质是直接触发MyClass.toUpperCase的类级调用,跟你外面new的myClass实例没有关联;你用实例引用去调静态方法本身就是Java不推荐的写法,编译阶段就会出警告,这种调用Spock根本拦截不到。 - 你直接通过
new MyClass()拿到的是原生普通Java对象,没有经过Spock的字节码增强处理,Spock根本没法追踪这个对象内部的方法调用链路,自然统计不到方法交互次数。 - 额外还有个语法问题:then子句后面多写了一个无意义的空字符串
"",也会干扰测试正常执行。
修改方案
最省事、最符合面向对象设计规范的改法不需要引入额外依赖,两步就能解决:
- 把
MyClass里两个方法的static修饰符全部删掉,改成普通实例方法:
class MyClass { public String getName(String input) { return toUpperCase(input); } public String toUpperCase(String name) { return name.toUpperCase(); } }
- 测试类里不要直接new真实对象,用Spock自带的
Spy()生成被测试实例——Spy是对真实对象的代理包装,既不会修改原有方法的执行逻辑,又能拦截所有方法调用做交互次数统计;同时删掉then子句后多余的空字符串:
class MyClassTest extends Specification { def 'check uppercase scenario'() { given: MyClass myClass = Spy() when: myClass.getName("test") then: 1 * myClass.toUpperCase("test") } }
改完直接运行就能正常验证方法调用次数。
如果你因为业务限制必须保留静态方法,需要额外引入PowerMock或者使用Spock 2.x以上版本的
MockedStatic能力,对静态方法做字节码级别的Mock拦截,但这种方案编写成本高,同时暴露了代码耦合度过高的设计问题,非必要不推荐使用。
内容的提问来源于stack exchange,提问作者user19471184
相关产品推荐
相关产品推荐

