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

Spring Java测试:调用真实类B时如何Mock类C的返回结果?

我来帮你搞定这个问题!你现在的核心问题是Mock的C没有和真实的B关联起来,导致B还是调用了容器里的真实C实例。咱们一步步来解决:

问题根源分析

你当前的测试代码里,@Mock出来的B和C都是独立的Mock对象,并没有和Spring容器中真实的A、B建立关联:

  • 真实的A里注入的是容器中的真实B,而不是你Mock的B
  • 真实的B里注入的是容器中的真实C,完全没用到你Mock的C
  • 甚至你还错误地Mock了B,这和你“真实调用B”的需求矛盾
解决方案:两种可行方式

方案一:用@MockBean替换Spring容器中的C(推荐)

@MockBean是Spring Test提供的注解,它会自动替换Spring上下文中的对应Bean。这样真实的B在依赖注入C时,拿到的就是我们Mock的实例,完美满足“真实调用B,Mock C”的需求。

修改后的测试代码:

@SpringBootTest
@RunWith(SpringRunner.class)
public class TestA {
    @Autowired
    private A a; // 注入真实的A,里面的B也是真实实例
    
    @MockBean
    private C c; // 替换Spring容器中的C为Mock对象

    @Test
    public void mytest() {
        // 设定Mock的C的返回值
        when(c.callC()).thenReturn(1);
        
        a.handle(); // 调用真实A的handle方法,会触发真实B的call,再调用Mock的C的callC
        
        verify(c, times(1)).callC(); // 验证Mock的C确实被调用了一次
    }
}

方案二:手动将Mock的C注入到真实B中

如果你不想替换整个容器的C,也可以手动获取真实的B,再把Mock的C注入进去:

@SpringBootTest
@RunWith(SpringRunner.class)
public class TestA {
    @Autowired
    private A a;
    
    @Autowired
    private B realB; // 获取容器中的真实B实例
    
    @Mock
    private C mockC;

    @Before
    public void setUp() {
        // 用Spring的反射工具,把Mock的C注入到真实B的c字段中
        ReflectionTestUtils.setField(realB, "c", mockC);
    }

    @Test
    public void mytest() {
        when(mockC.callC()).thenReturn(1);
        
        a.handle();
        
        verify(mockC, times(1)).callC();
    }
}
额外注意点
  • 不要@Mock B!你的需求是真实调用B的逻辑,所以要让Spring注入真实的B实例
  • 原代码里的A.handle()是错误的,应该调用实例方法a.handle()(A不是静态类)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 06:47:35