为何使用Mockito doAnswer修改方法参数后,真实方法仍用原参数?
问题原因及解决方案
为什么修改invocation.getArguments()不生效?
Mockito的invocation.getArguments()返回的是方法调用参数的副本数组,不是传给真实方法的原始参数引用。当你调用reportBuilder.retrieveReport(Report.DEFAULT_ROW_SIZE)时,参数值已经被传递到方法调用的栈帧中,修改副本数组里的值根本不会影响真实方法接收到的参数,所以callRealMethod()还是会用原始的Report.DEFAULT_ROW_SIZE来执行。
正确的解决方式
根据你是否需要保留真实方法的逻辑,有两种处理方案:
方案1:直接返回测试用的Report(无需真实方法逻辑)
如果只是需要替换参数后的结果,不需要执行真实方法的逻辑,直接存根返回模拟对象即可:
int testSize = 5; // 构建你的测试用Report对象 Report mockReport = new Report(); when(reportBuilder.retrieveReport(anyInt())).thenReturn(mockReport);
方案2:必须调用真实方法,替换参数执行
如果你需要执行真实方法的逻辑,但要传入自定义参数,不要用invocation.callRealMethod(),而是手动调用spy对象的真实方法并传入新参数:
int testSize = 5; doAnswer(invocation -> { // 获取当前的spy对象,手动调用真实方法并传入自定义参数 ReportBuilder spyBuilder = (ReportBuilder) invocation.getMock(); return spyBuilder.retrieveReport(testSize); }).when(reportBuilder).retrieveReport(anyInt());
或者更直接的方式(如果spy对象在当前作用域可见):
int testSize = 5; doAnswer(invocation -> { return reportBuilder.retrieveReport(testSize); }).when(reportBuilder).retrieveReport(anyInt());
这样就能让真实方法接收你指定的testSize参数执行了。
内容的提问来源于stack exchange,提问作者Juan Bustamante
相关产品推荐
相关产品推荐

