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

如何验证Mockito mock调用时传入的可变对象在后续变更前的特定状态

问题原因说明

原有测试失败的核心原因:Mockito的verify动作是在业务方法执行完成后才执行,此时传入的可变对象已经被后续逻辑修改了状态,默认的参数匹配是基于修改后的对象状态做equals比较,自然和预期的调用时状态不符。

解决方案

通用方案:通过Answer在调用发生时实时捕获参数快照

该方案无需修改现有业务类,在mock方法被调用的瞬间(此时对象还未被后续逻辑修改)就保存状态快照,后续直接校验快照即可,兼容所有Mockito版本。

import org.junit.Test;
import java.util.concurrent.atomic.AtomicReference;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@Test
public void operationIsCalledWithSpecificState() {
    StatefulOperation operation = mock(StatefulOperation.class);
    // 存储调用时的参数状态快照
    AtomicReference<Stateful> capturedCallInput = new AtomicReference<>();

    // 定义mock方法的回调逻辑,调用时立刻保存参数状态
    when(operation.doOperation(any(Stateful.class))).thenAnswer(invocation -> {
        Stateful input = invocation.getArgument(0);
        // 基于当前状态创建副本存入,避免后续对象修改影响快照
        capturedCallInput.set(new Stateful(input.getValue()));
        return null; // 如果doOperation有返回值按实际类型返回即可
    });

    StatefulService statefulService = new StatefulService(operation);
    statefulService.execute(new Stateful("Input"));

    // 先校验方法确实被调用了一次
    verify(operation).doOperation(any(Stateful.class));
    // 校验调用时的参数状态和预期一致
    assertEquals(new Stateful("Input"), capturedCallInput.get());
}

多调用场景适配

如果需要校验同一个mock方法被多次调用的参数状态,只需要把AtomicReference换成List存储多个快照即可:

List<Stateful> capturedInputs = new ArrayList<>();
when(operation.doOperation(any(Stateful.class))).thenAnswer(invocation -> {
    Stateful input = invocation.getArgument(0);
    capturedInputs.add(new Stateful(input.getValue()));
    return null;
});
// 后续校验list里的元素顺序和状态即可

内容的提问来源于stack exchange,提问作者M. Justin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 13:18:01