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

为何使用@SpyBean配置Mock时会触发真实方法调用?

@SpyBean配置Mock时真实方法触发的原因及解决办法

问题场景

业务类代码:

@Service
class A(){
 fun someMethod():String{
  println("inside real method")
  return "result"
 } 
}

使用@SpyBean的测试代码:

@SpyBean
private lateinit var a:A

@Test
fun test(){
 println("before mock")
 Mockito.`when`(a.someMethod()).doReturn("mock_result")
 println("empty test ended")
}

执行结果:

before mock
inside real method
empty test ended

替换为@MockBean后的测试代码:

@MockBean
private lateinit var a:A

@Test
fun test(){
 println("before mock")
 Mockito.`when`(a.someMethod()).doReturn("mock_result")
 println("empty test ended")
}

执行结果:

before mock
empty test ended

核心疑问:明明未直接调用方法,仅配置Mock时,@SpyBean场景下真实方法就被触发,且尝试doReturn、thenReturn、doAnswer、thenAnswer均有此现象。

原因分析

这是Mockito中Spy和Mock的本质差异导致的:

  • @MockBean 创建的是完全模拟对象,所有方法默认不会执行真实逻辑,仅返回默认值(如null、空集合等),所以配置when(...).doReturn(...)时不会触发真实方法。
  • @SpyBean 是对真实对象的包装(部分模拟),默认会执行真实方法逻辑。当使用Mockito.when(a.someMethod()).doReturn(...)这种语法时,Mockito需要先调用一次真实的someMethod()来获取方法调用的“桩点”,才能完成后续的返回值替换配置,这就导致了真实方法被执行。

解决办法

要避免Spy场景下配置Mock时触发真实方法,换用**doReturn(...).when(...)的语法顺序**即可,这种方式不会预先调用真实方法:

@SpyBean
private lateinit var a:A

@Test
fun test(){
 println("before mock")
 Mockito.doReturn("mock_result").`when`(a).someMethod()
 println("empty test ended")
}

调整后,真实方法不会被触发,执行结果与@MockBean场景一致。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 09:40:32