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会把这个未验证的调用判定为“多余交互”,从而抛出异常。 - 两种解决路径:
- 在
testExecute_numberOfTimes方法里添加对provider.readScenarios()的验证,比如:
这样Mockito就会把这个调用标记为已预期,不会在verify(provider).readScenarios();verifyNoMoreInteractions时报错。 - 如果不需要验证
provider的调用,直接删除tearDown里的verifyNoMoreInteractions(provider)语句即可。
- 在
- 额外提醒:确保
prepareScenarioList()返回的场景列表不为空,否则循环里的scenarioList.get(currentIndex)会抛出索引越界异常。
内容的提问来源于stack exchange,提问作者Yurii
相关产品推荐
相关产品推荐

