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

如何使用Mockito模拟Java链式依赖?类调用链测试空指针问题求解

嘿,这个问题我之前也碰到过!核心原因是你用@Spy创建的B对象并没有自动注入它依赖的C,所以调用方法时才会抛出空指针异常。要不用when-then语法就让流程走到c.callAnother(),其实只要给Spy的B补上C的实例就行,给你几个实用的方案:

方案1:Spring环境下用@SpyBean(推荐)

如果你的测试是基于Spring Boot的,直接把@Spy换成@SpyBean就搞定了——Spring会自动帮你把B的依赖C注入进去,不管C是真实的Bean还是你Mock的Bean都能正常工作。

修改后的ATest代码:

@SpringBootTest
class ATest {
    @SpyBean
    private B b;

    @Test
    void someMethod() {
        // 现在B里的C已经被Spring自动注入,调用时会正常走到c.callAnother()
        b.callAnotherMethodAndGetValue();
    }
}
方案2:纯Mockito环境手动注入C

如果是没有Spring容器的纯Mockito测试,你可以手动创建C的实例(真实对象或者Mock对象),然后通过Setter或者反射注入到Spy的B中:

class ATest {
    @Spy
    private B b;
    // 可以是真实的C实例,也可以用@Mock注解创建Mock对象
    private C c = new C(); // 或者@Mock private C c;

    @BeforeEach
    void setUp() {
        // 如果B有setC()方法,直接调用注入
        b.setC(c);
        
        // 要是B没有公开的Setter,用反射搞定:
        // try {
        //     Field field = B.class.getDeclaredField("c");
        //     field.setAccessible(true);
        //     field.set(b, c);
        // } catch (Exception e) {
        //     e.printStackTrace();
        // }
    }

    @Test
    void someMethod() {
        b.callAnotherMethodAndGetValue(); // 现在会正常执行到c.callAnother()
    }
}
方案3:用@InjectMocks让Mockito自动注入

如果你的测试类里已经有C的实例(比如用@Mock创建的C),可以结合@InjectMocks让Mockito自动把C注入到Spy的B中:

class ATest {
    @Mock
    private C c;
    @Spy
    @InjectMocks
    private B b;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.openMocks(this); // 初始化Mock和Spy对象
    }

    @Test
    void someMethod() {
        b.callAnotherMethodAndGetValue(); // 会正常走到c.callAnother(),这里的C是Mock对象
    }
}

这几种方案都不需要用when-then来Stub B的方法,而是让Spy的B真正执行自身的业务逻辑,同时依赖的C也能正常工作,自然就会走到c.callAnother()了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:58:40