为何Mockito参数匹配器无法识别建造者模式创建的对象?
Groovy测试中Mockito ArgumentCaptor无法识别自定义对象的原因与解决办法
自定义Java类代码
package com.example.objects; import java.util.Objects; public class MyExampleClass extends SomeBaseClass { private String param1; private String param2; private MyExampleClass(String param1, String param2) { this.param1 = param1; this.param2 = param2; } MyExampleClass() { } public String getParam1() { return param1; } public String getParam2() { return param2; } public static class Builder { private String param1; private String param2; public Builder setParam1(String param1) { this.param1 = param1; return this; } public Builder setParam2(String param2) { this.param2 = param2; return this; } public MyExampleClass build() { Objects.requireNonNull(param1,"blahblah"); Objects.requireNonNull(param2,"blahblah"); return new MyExampleClass(param1, param2); } } }
Groovy测试代码
def captor = ArgumentCaptor.forClass(MyExampleClass) Mockito.verify(mockObject).someMethod(captor.capture())
报错信息
Wanted but not invoked: mockObject.someMethod( <Capturing argument> ); -> at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47) However, there was exactly 1 interaction with this mock: mockObject.someMethod( com.example.objects.MyExampleClass@47a7a101 );
原因分析
问题核心是Groovy与Java的方法调用机制差异:
- Java中,
Mockito.verify(mock).method(captor.capture())会将captor.capture()识别为参数匹配器(Matcher),用于捕获方法实际接收的参数。 - Groovy中会优先执行
captor.capture(),将其返回的默认值(对象类型为null)作为参数传递给someMethod,而非把capture()本身作为Matcher注册给Mockito。这导致Mockito期望的是someMethod(null),但实际调用的是someMethod(MyExampleClass实例),最终匹配失败报错。
解决办法
方法1:用括号强制参数传递逻辑
通过额外括号让Groovy将captor.capture()作为参数传递,而非提前执行:
def captor = ArgumentCaptor.forClass(MyExampleClass) Mockito.verify(mockObject).someMethod((captor.capture()))
方法2:使用@Captor注解创建捕获器
借助Mockito的@Captor注解可以规避Groovy动态解析的问题,代码更简洁:
import org.mockito.Captor import org.mockito.MockitoAnnotations @Captor ArgumentCaptor<MyExampleClass> captor @Before void setup() { MockitoAnnotations.openMocks(this) // 初始化注解 } void testMethod() { // 执行测试逻辑... Mockito.verify(mockObject).someMethod(captor.capture()) // 断言捕获到的对象 def capturedObj = captor.value assert capturedObj.param1 == "预期值" }
方法3:显式使用匹配器包裹
通过Mockito.argThat包裹捕获逻辑,确保Groovy正确识别Matcher:
def captor = ArgumentCaptor.forClass(MyExampleClass) Mockito.verify(mockObject).someMethod(Mockito.argThat { captor.capture() return true })
内容的提问来源于stack exchange,提问作者Lord Arryn
相关产品推荐
相关产品推荐

