You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Spock替代JUnit编写单元测试时Mock Provider<T>.get()遭遇MissingMethodInvocationException的原因排查

解决Spock中Mock Provider时的MissingMethodInvocationException问题

你遇到的核心问题是混用了Spock原生Mock和Mockito的API——这两个框架的Mock机制完全独立,不能混搭使用,咱们一步步拆解原因和解决方案:

为什么第一种方式会抛出异常

你用Provider<SomeOjb> a = Mock()创建的是Spock原生生成的Mock对象,而非Mockito的Mock实例。Mockito的when()方法只能识别自己框架生成的Mock,当你把Spock Mock传给它时,它根本认不出这是一个Mockito Mock,自然就会抛出MissingMethodInvocationException,提示你传入的不是Mockito Mock上的方法调用。

第二种方式的语法错误原因

Groovy对泛型尖括号<>的语法解析和Java略有不同:直接写def a = Mock(Provider<SomeObj>)时,Groovy会错误地把<>当成比较运算符,导致语法报错。正确的写法有两种:

  • 显式指定变量类型:Provider<SomeObj> a = Mock()
  • 用类型转换:def a = Mock(Provider) as Provider<SomeObj>

第三种方式正常工作的原因

你用@Mock Provider<SomeObj> a;注解创建的是Mockito的Mock对象(前提是你给测试类加了Mockito的扩展,比如@ExtendWith(MockitoExtension.class)或者Spock的Mockito集成配置),这时候配合Mockito的when().thenReturn()完全是配套用法,所以能正常运行。


正确的两种实现方式

方式一:纯Spock原生Mock(推荐)

Spock自带的Mock语法比Mockito更简洁,完全不需要依赖Mockito的API:

Provider<SomeObj> a = Mock()

def setup() {
    SomeObj obj = new SomeObj()
    // Spock用>>来指定方法返回值,等价于Mockito的when().thenReturn()
    a.get() >> obj
}

方式二:纯Mockito Mock(适合习惯Mockito语法的场景)

如果你更熟悉Mockito的写法,确保全程用Mockito的Mock创建方式:

@Mock
Provider<SomeObj> a

def setup() {
    SomeObj obj = new SomeObj()
    Mockito.when(a.get()).thenReturn(obj)
}

记得给测试类添加Mockito扩展注解:@ExtendWith(MockitoExtension.class),或者在Spock的配置中启用Mockito集成。


内容的提问来源于stack exchange,提问作者Suule

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 05:12:36