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

Mockito Spy使用时Mock函数未被调用的问题排查

Mockito测试中Mock对象未调用问题排查与解决

场景与代码

类A的fun()方法会调用依赖类B的fun1()、类C的fun2(),同时调用自身的fun3()。

类A代码

class A {
    B b;
    C c;

    @Inject
    A(B b, C c) {
        this.b = b;
        this.c = c;
    }

    void fun() {
        try {
            b.fun1();
            c.fun2("success");
        } catch (Exception e) {
            c.fun2("Failure");
        }
        fun3();
    }

    void fun3() {
        // 业务代码
    }
}

JUnit测试代码

public class ATest {
    @Mock
    B b;
    @Mock
    C c;
    @InjectMocks
    A a;
    @Mock
    Fun1Response fun1response;

    @Test
    public void myTest() {
        when(b.fun1(any())).thenReturn(fun1response);
        A aSpy = Mockito.spy(a);
        doNothing().when(aSpy).fun3();
        doNothing().when(c).fun2(any());
        aSpy.fun();
        verify(c).fun2(eq("success"));
        verify(a).fun3();
    }
}

运行错误

期望但未调用:
c.fun2(<any>)
[junit] 实际:与该Mock对象无任何交互。

问题原因分析

  1. Mockito注解未初始化:测试类使用了@Mock和@InjectMocks注解,但未配置Mockito运行器/扩展,导致注解失效,b、c及a中的依赖均为null。调用b.fun1()时抛出NullPointerException,进入catch块后调用c.fun2()再次抛出NullPointerException,该异常未被外层捕获,导致fun()方法提前终止,c.fun2()从未实际执行。

  2. 方法存根签名不匹配:类A中调用的是无参的b.fun1(),但测试代码中使用了带参数匹配器的when(b.fun1(any())),触发Mockito参数匹配器使用错误,存根无效;若B.fun1()是void方法,使用thenReturn()存根的写法本身错误(void方法需用doNothing()/doThrow())。

  3. Verify对象不匹配:测试中调用的是aSpy.fun(),但verify(a).fun3()验证的是原始a对象的方法,而非被调用的aSpy,会导致验证失败。

解决步骤

步骤1:初始化Mockito注解

根据JUnit版本添加对应配置:

  • JUnit 4:在测试类上添加@RunWith(MockitoJUnitRunner.class),或在@Before方法中调用MockitoAnnotations.initMocks(this);
  • JUnit 5:在测试类上添加@ExtendWith(MockitoExtension.class)

示例(JUnit 5):

@ExtendWith(MockitoExtension.class)
public class ATest {
    // 原有代码
}

步骤2:修正方法存根

若B.fun1()是无参void方法,修正存根代码:

// 替换原有的when(b.fun1(any())).thenReturn(fun1response);
doNothing().when(b).fun1();

若B.fun1()是有参方法,需确保类A调用与测试存根参数匹配,例如类A中调用b.fun1("param"),则存根改为:

when(b.fun1(eq("param"))).thenReturn(fun1response);

步骤3:修正Verify对象

将验证fun3()的对象改为aSpy:

// 替换原有的verify(a).fun3();
verify(aSpy).fun3();

完整修正后的测试代码

@ExtendWith(MockitoExtension.class)
public class ATest {
    @Mock
    B b;
    @Mock
    C c;
    @InjectMocks
    A a;

    @Test
    public void myTest() {
        // 修正fun1()的存根(假设是无参void方法)
        doNothing().when(b).fun1();
        A aSpy = Mockito.spy(a);
        doNothing().when(aSpy).fun3();
        doNothing().when(c).fun2(any());
        
        aSpy.fun();
        
        verify(c).fun2(eq("success"));
        // 修正verify的对象为aSpy
        verify(aSpy).fun3();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 19:05:23