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

Mockito将未验证的Mock标记为已验证?JUnit5测试异常问询

问题描述

我在JUnit5测试中使用Mockito.verifyNoMoreInteractions(mock1, mock2, ...)方法,近期发现该方法无法检测出未验证的Mock调用——明明我忘记编写对应的verify()语句。
调试时通过Mockito.mockingDetails(mock).getInvocations()查看Mock的调用记录,意外发现Mock方法被调用后,对应的调用记录的verified字段直接被设为true,导致verifyNoMoreInteractions()无法识别这些未显式验证的调用。
我原本认为所有Mock调用都需要通过显式的verify()调用标记为已验证,想知道是我的理解有误,还是Mockito存在问题?

附上本应失败却运行通过的测试类:

@ExtendWith(MockitoExtension.class)
class UserManagerTest {

    UserManager userManager;

    @Mock
    DataNetworkPlugin dataNetworkPlugin;

    @Mock
    Source source;

    @BeforeEach
    void setUp() {
        initializeTest();
    }

    @AfterEach
    void tearDown() {
        verifyNoMoreInteractions(source, dataNetworkPlugin);
    }

    @Test
    void test() {
        System.out.println("test");
    }

    private void initializeTest() {         
        when(dataNetworkPlugin.getElement(anyString())).thenReturn(source);
        when(source.asDataSource()).thenReturn(null);

        userManager = UserManager.createInstance(dataNetworkPlugin);
    }
}

注:dataNetworkPlugin.getElement("")和source.asDataSource()均在UserManager.createInstance()内部被调用。

更新2:修改tearDown方法后测试仍能运行,Mockito未提示过度验证:

@AfterEach
void tearDown() {
    verify(source).asDataSource();
    verify(dataNetworkPlugin).getElement();
    verifyNoMoreInteractions(source, dataNetworkPlugin);
}
原因分析与解决方案

这是因为Mockito默认会将when()存根时触发的调用自动标记为已验证。

在你的测试代码中,initializeTest()方法里调用when(dataNetworkPlugin.getElement(anyString()))时,Mockito的存根语法会实际执行一次dataNetworkPlugin.getElement()的Mock方法调用——这是when().thenReturn()语法的固有特性。同理,when(source.asDataSource()).thenReturn(null)也会触发一次source.asDataSource()的调用。这些存根阶段产生的调用,会被Mockito自动标记为verified=true,所以后续的verifyNoMoreInteractions()会直接忽略它们。

你的理解偏差在于:并非所有Mock调用都需要显式的verify()验证,Mockito对存根过程中产生的调用会自动“豁免”验证。

如果想要让verifyNoMoreInteractions()检测到UserManager.createInstance()中的调用,你需要改用**doReturn()的存根语法**,避免存根时触发真实的Mock方法调用:

private void initializeTest() {         
    doReturn(source).when(dataNetworkPlugin).getElement(anyString());
    doReturn(null).when(source).asDataSource();

    userManager = UserManager.createInstance(dataNetworkPlugin);
}

修改后,存根阶段不会触发Mock方法的实际调用,只有UserManager.createInstance()里的调用会被记录为未验证的调用,此时verifyNoMoreInteractions()就会按预期失败,直到你添加对应的verify()语句。

另外,更新2中测试通过的原因是:你显式验证的调用,和存根+初始化阶段的调用完全对应,没有额外未验证的调用,所以verifyNoMoreInteractions()不会抛出错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 10:20:23