Mockito捕获参数getAllValues返回重复值问题求助
问题分析与解决方案
核心问题定位
你遇到的捕获参数值一致的问题,90%概率是生产代码中复用了同一个OrderParams实例:两次调用modifyOrder时,都是修改同一个对象的price属性(先设525,再改475),而Mockito的ArgumentCaptor捕获的是对象引用,不是快照。所以最终两次捕获到的都是同一个对象,其price值是最后一次修改的475。
另外,你的依赖配置中spring-boot-starter-test已经自带了Mockito,手动添加的mockito-core可能和starter的版本冲突,这也可能导致一些诡异的行为。
分步解决方案
1. 修复生产代码的对象复用问题
检查调用modifyOrder的生产代码:
- 如果是同一个
OrderParams对象被重复修改,每次调用前创建新的实例:// 第一次调用:创建新实例 OrderParams params1 = new OrderParams(); params1.setPrice(525.0); kiteOrderService.modifyOrder(params1, profitBracketOrder.getOrder().orderId); // 第二次调用:创建新实例 OrderParams params2 = new OrderParams(); params2.setPrice(475.0); kiteOrderService.modifyOrder(params2, profitBracketOrder.getOrder().orderId); - 如果必须复用对象,需要在每次调用前深拷贝对象,确保每次传递的是不同的实例。
2. 调整测试代码(无需修改生产代码的替代方案)
如果暂时无法修改生产代码,用Mockito的Answer来记录每次调用时的参数快照,而不是依赖ArgumentCaptor:
// 初始化一个列表记录每次调用的price值 List<Double> capturedPrices = new ArrayList<>(); // 拦截modifyOrder调用,记录每次的price doAnswer(invocation -> { OrderParams params = invocation.getArgument(0); // 复制值避免后续修改影响记录 capturedPrices.add(new Double(params.getPrice())); return null; // 根据modifyOrder的返回类型调整,比如返回Order则return mock(Order.class) }).when(mockKiteOrderService).modifyOrder(any(OrderParams.class), eq("3")); // 执行你的测试逻辑 // ... // 断言结果 assertThat(capturedPrices.get(0)).isEqualTo(525.0); assertThat(capturedPrices.get(1)).isEqualTo(475.0);
3. 统一Mockito版本,解决依赖冲突
- 先查看当前项目实际使用的Mockito版本:
执行Gradle命令:./gradlew dependencies --configuration testRuntimeClasspath | grep mockito - 统一版本:
- 如果你想用指定的5.3.1版本,在build.gradle中强制指定:
dependencies { // ... 其他依赖 testImplementation('org.mockito:mockito-core:5.3.1') { force = true // 强制使用该版本,覆盖starter自带的版本 } testImplementation('org.mockito:mockito-junit-jupiter:5.3.1') { force = true // JUnit5扩展也要对应版本 } } - 或者直接移除手动添加的
mockito-core,使用spring-boot-starter-test自带的版本,确保版本一致性。
- 如果你想用指定的5.3.1版本,在build.gradle中强制指定:
内容的提问来源于stack exchange,提问作者Kannan J
相关产品推荐
相关产品推荐

