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

循环添加Mockito存根触发异常:API使用错误问题排查

Mockito异常:存储OngoingStubbing后多次调用thenReturn不被允许的原因及解决方法

问题原因

Mockito的OngoingStubbing实例是为一次性链式配置设计的,它的核心逻辑是在同一个调用链中完成所有存根行为的定义(比如when(mock.method()).thenReturn(a).thenReturn(b)),并不支持将实例存储为变量后分多次调用thenReturn这类存根方法。

当你把OngoingStubbing存为变量并循环调用thenReturn时,会破坏Mockito内部的状态管理机制——每次调用存根方法时,Mockito会更新内部的行为链,但这个实例并未被设计为可重复调用的载体,因此直接触发了API使用违规的异常。

注意:lenient()的作用是放宽存根的严格匹配检查(比如允许未使用的存根),但它不会改变Mockito核心API的调用规则,所以添加lenient()无法解决这个问题。

解决方案

方案1:直接链式配置多返回值

Mockito支持在单个thenReturn调用中传入多个参数,或者通过链式调用thenReturn来依次定义每次调用的返回值,这是最符合Mockito API设计的方式:

@Test
public void thisTestFixed() {
    // 生成RETRY_TIMES+1个null,再加上非空值
    ReturnValueDep[] stubValues = new ReturnValueDep[RETRY_TIMES + 1];
    Arrays.fill(stubValues, null);
    
    lenient().when(mockedDep.mockedMethod(eq("mockedValue")))
            .thenReturn(stubValues) // 前RETRY_TIMES+1次返回null
            .thenReturn(SOME_NON_NULL_VALUE); // 后续调用返回非空值

    assertThrows(SomeException.class, () -> testObj.mainMethod());
}

如果返回值数量少,也可以直接写链式调用:

// 假设RETRY_TIMES=3,即4次null,再一次非空
lenient().when(mockedDep.mockedMethod(eq("mockedValue")))
        .thenReturn(null)
        .thenReturn(null)
        .thenReturn(null)
        .thenReturn(null)
        .thenReturn(SOME_NON_NULL_VALUE);

方案2:用Answer动态控制返回值

如果需要更灵活的逻辑(比如根据调用次数动态返回),可以使用Answer接口来自定义存根行为:

@Test
public void thisTestFixedWithAnswer() {
    AtomicInteger callCounter = new AtomicInteger(0);
    
    lenient().when(mockedDep.mockedMethod(eq("mockedValue")))
            .thenAnswer(invocation -> {
                int callCount = callCounter.incrementAndGet();
                // 前RETRY_TIMES+1次返回null,后续返回非空值
                return callCount <= RETRY_TIMES + 1 ? null : SOME_NON_NULL_VALUE;
            });

    assertThrows(SomeException.class, () -> testObj.mainMethod());
}

内容的提问来源于stack exchange,提问作者Kate

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 13:12:44