Mockito参数匹配器报错:方法签名匹配仍抛出异常
问题重现
在SpringBoot集成Mockito的测试场景中,对方法getCaseNumberByContactInfoAndBatchDate使用any()系列参数匹配器打桩,参数数量与匹配器数量一致,但仍抛出InvalidUseOfMatchersException异常,更换匹配器类型后问题依旧。
测试代码
@Test public void checkSFCaseExist_success_listIsNull_size0() { when(salesForceServiceClient.getCaseNumberByContactInfoAndBatchDate(any(), any(), any())).thenReturn(isNull()); ResponseDto responseDto = manualRiskCasePipeline.checkSFCaseExist(ParameterVO.merchantAccountNumber, ParameterVO.merhantRealmId, ParameterVO.email, ParameterVO.batchDate, ParameterVO.authHeader); assertNotNull(responseDto); assertTrue(responseDto.getErrorMessage().equalsIgnoreCase("IBOSS risk case does not exist.")); }
报错信息
Invalid use of argument matchers!
3 matchers expected, 1 recorded:
-> at com.intuit.v4.money.risk.ibossdecisionsvcapp.ManualRiskCasePipelineTest.checkSFCaseExist_success_listIsNull_size0(ManualRiskCasePipelineTest.java:94)This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(any(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(any(), eq("String by matcher"));For more info see javadoc for Matchers class.
...
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
3 matchers expected, 1 recorded:
目标方法声明
List<String> getCaseNumberByContactInfoAndBatchDate(CaseSearchDO var1, String var2, String var3);
原因分析
核心问题出在**thenReturn(isNull())的误用**:
isNull()是Mockito的参数匹配器,仅用于匹配方法的输入参数,不能用来指定方法的返回值。- Mockito会扫描整个
when(...).thenReturn(...)调用链中的所有匹配器,当它发现你在返回值位置使用了匹配器时,会打乱匹配器的计数逻辑,导致出现"3个匹配器预期,仅记录到1个"的异常。
解决办法
将thenReturn(isNull())替换为实际的返回值,根据你的测试场景(模拟返回空列表/Null来触发错误信息),可以选择以下两种方式:
方式1:返回Null
如果需要模拟方法返回Null,直接使用null作为返回值,同时建议用精确匹配器对应参数类型,提升代码可读性:
when(salesForceServiceClient.getCaseNumberByContactInfoAndBatchDate(any(CaseSearchDO.class), anyString(), anyString())).thenReturn(null);
方式2:返回空列表
如果业务逻辑中是通过空列表判断不存在,更推荐返回空列表而非Null:
import java.util.Collections; // ... when(salesForceServiceClient.getCaseNumberByContactInfoAndBatchDate(any(CaseSearchDO.class), anyString(), anyString())).thenReturn(Collections.emptyList());
优化后的完整测试代码
@Test public void checkSFCaseExist_success_listIsNull_size0() { when(salesForceServiceClient.getCaseNumberByContactInfoAndBatchDate(any(CaseSearchDO.class), anyString(), anyString())).thenReturn(Collections.emptyList()); ResponseDto responseDto = manualRiskCasePipeline.checkSFCaseExist(ParameterVO.merchantAccountNumber, ParameterVO.merhantRealmId, ParameterVO.email, ParameterVO.batchDate, ParameterVO.authHeader); assertNotNull(responseDto); assertTrue(responseDto.getErrorMessage().equalsIgnoreCase("IBOSS risk case does not exist.")); }
内容的提问来源于stack exchange,提问作者user204069

