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

Mockito抛出NoInteractionsWanted异常,排查Provider额外交互来源

问题

我正在为一款后续将迁移至Spring Boot的纯Java服务编写测试用例。该服务类从JSON读取若干场景,并通过ScenarioHandler接口循环处理这些场景,核心代码如下:

@Override
public void execute(ScenarioHandler handler) {
    execute(handler, () -> false);
}

public void execute(ScenarioHandler handler, TerminatorListener terminator) {
    List<Scenario> scenarioList = provider.readScenarios();
    validateScenarios(scenarioList);
    listen(scenarioList, handler, terminator);
}

private void listen(List<Scenario> scenarioList, ScenarioHandler handler, TerminatorListener terminator) {
    int currentIndex = 0;
    while (!terminator.shouldTerminate()) {
        Scenario scenario = scenarioList.get(currentIndex);
        handler.onScenarioReceived(scenario);
        currentIndex = (currentIndex + 1) % scenarioList.size();
        sleep();
    }
}

运行测试时抛出org.mockito.exceptions.verifications.NoInteractionsWanted异常,堆栈信息如下:

No interactions wanted here:
-> at executor.service.service.ScenarioSourceListenerTest.tearDown(ScenarioSourceListenerTest.java:65)
But found this interaction on mock 'scenarioProvider':
-> at executor.service.service.impl.ScenarioSourceListenerImpl.execute(ScenarioSourceListenerImpl.java:30)
Actually, above is the only interaction with this mock.

我的测试代码如下:

private ScenarioProvider provider;

private ScenarioHandler handler;

@BeforeEach
public void setUp() {
    provider = mock(ScenarioProvider.class);
    handler = mock(ScenarioHandler.class);
    listener = new ScenarioSourceListenerImpl(provider);
}

@Test
public void testExecute_numberOfTimes() {
    int maxIterations = 5;
    TerminatorListener terminator = new TestTerminator(maxIterations);

    given(provider.readScenarios()).willReturn(prepareScenarioList());

    listener.execute(handler, terminator);

    verify(handler, times(maxIterations)).onScenarioReceived(any(Scenario.class));
}

@AfterEach
void tearDown() {
    verifyNoMoreInteractions(provider);
    verifyNoMoreInteractions(handler);
}

private class TestTerminator implements TerminatorListener {
    private int maxIterations;
    private int currentIteration = 0;

    public TestTerminator(int maxIterations) {
        this.maxIterations = maxIterations;
    }

    @Override
    public boolean shouldTerminate() {
        currentIteration++;
        return currentIteration > maxIterations;
    }
}

请问可能存在哪些未被预期的与provider的交互?

原因分析与解决办法
  • 问题核心在于tearDown方法里的verifyNoMoreInteractions(provider)。测试执行时,代码明确调用了provider.readScenarios(),但你没有在测试方法里对这个调用做显式验证,Mockito会把这个未验证的调用判定为“多余交互”,从而抛出异常。
  • 两种解决路径:
    1. 在testExecute_numberOfTimes方法里添加对provider.readScenarios()的验证,比如:
      verify(provider).readScenarios();
      
      这样Mockito就会把这个调用标记为已预期,不会在verifyNoMoreInteractions时报错。
    2. 如果不需要验证provider的调用,直接删除tearDown里的verifyNoMoreInteractions(provider)语句即可。
  • 额外提醒:确保prepareScenarioList()返回的场景列表不为空,否则循环里的scenarioList.get(currentIndex)会抛出索引越界异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 02:26:08