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

JUnit5 Mockito测试如何让被Mock类方法真实调用内部依赖

问题场景

现有三层Spring依赖类结构如下:

Class A (test)
    .
    -> Autowired B 
           .
           -> Autowired C

A.method {
    b.method2();
}

B.method2 {
    c.method3();
}

当前编写A类的单元测试,初始测试代码结构如下:

@InjectMocks 
A a;

@Mock
B b;

// 测试逻辑中调用
a.method();

现存问题:由于B是@Mock标注的纯模拟对象,调用*b.method2()时默认不会执行任何内部逻辑,无法走到后续c.method3()*的调用。实际需要达成两个目标:

  • 调用a.method()时,*b.method2()执行真实业务逻辑,最终触发对c.method3()*的调用
  • 可以正常通过Mockito.when(c.method3()).thenReturn(1);给*c.method3()*设置返回值存根

实现方案

该需求可以实现,核心是用Spy对象替代纯Mock的B实例,手动补全B的依赖注入即可,操作步骤如下:

  • 将B字段上的@Mock注解替换为@Spy注解。@Spy生成的包装对象默认会走对应方法的真实逻辑,只有被显式存根的方法才会执行模拟逻辑,刚好满足b.method2()走真实代码的需求。
  • 给依赖C添加@Mock注解,让C成为Mockito管控的模拟对象,支持后续存根设置。
  • 手动完成B对C的依赖注入:@InjectMocks只会自动注入A的依赖,不会给Spy包装的B注入它依赖的C实例,需要在测试初始化方法中通过反射工具注入即可,一般用Spring Test自带的ReflectionTestUtils就可以实现。
  • 正常对c.method3()做返回值存根,不需要额外存根b.method2(),调用时会自动执行B的真实逻辑,内部调用到c.method3()时就会返回预设的存根值。

完整测试代码参考:

@InjectMocks
A a;

@Spy
B b;

@Mock
C c;

@BeforeEach // JUnit4环境替换为@Before注解
void setUp() {
    // 把Mock生成的C实例注入到Spy的B对象中
    ReflectionTestUtils.setField(b, "c", c);
    // 设置c.method3()的存根返回值
    Mockito.when(c.method3()).thenReturn(1);
}

@Test
void testAMethod() {
    // 执行被测方法
    a.method();
    
    // 可按需添加断言、调用验证逻辑
    Mockito.verify(c, Mockito.times(1)).method3();
}

补充说明:如果后续部分用例需要b.method2()不走真实逻辑,直接用Mockito给b.method2()单独做存根即可,Spy对象支持对单个方法做模拟覆盖,灵活性比纯Mock对象更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 04:18:13