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

Kotlin1.5下Mockk1.12.0深度存根链式调用验证失败求解

问题原因

报错的根因非常明确:
你代码的play方法中一共两次访问了notifier.action属性:第一次是调用notifier.action.getSteps()遍历步数,第二次是满足条件时调用notifier.action.send()发通知,对应Mockk层面就是触发了两次Notifier.getAction()调用。
而你直接写every { notifier.action.getSteps() }这种链式打桩语法时,Mockk会隐式为notifier.action生成一个临时mock实例,这个隐式打桩默认只允许1次action属性访问,第二次访问就会触发调用次数不匹配的断言错误。

可行解决方案

方案1:显式Mock中间依赖(最稳定,推荐)

单独Mock Action实例,手动绑定到Notifier的action属性,避免Mockk生成临时隐式mock:

@ExtendWith(MockKExtension::class)
class ServiceTest {
  @MockK private lateinit var rabbit: Rabbit
  @MockK private lateinit var action: Action // 单独声明Action的mock
  @MockK private lateinit var notifier: Notifier

  @InjectMockKs private lateinit var service: Service

  @Test
  fun `One notification should be sent`() {
    // 先给notifier的action属性打桩,返回我们单独mock的Action实例
    every { notifier.action } returns action
    // 直接给Action实例的方法打桩,不需要写链式路径
    every { action.getSteps() } returns listOf(1, 2, 3)
    every { rabbit.jump(1) } returns false
    every { rabbit.jump(2) } returns false
    every { rabbit.jump(3) } returns true
    every { action.send() } returns 1

    service.play()

    verify(exactly = 3) { rabbit.jump(any()) }
    verify(exactly = 1) { action.send() }
  }
}

这种方案适配你的RedisTemplate场景也非常方便:你可以单独Mock opsForSet()返回的SetOperations实例,先打桩every { redisTemplate.opsForSet() } returns 你mock的SetOperations实例,后续直接给SetOperations的members、remove等方法打桩即可。

方案2:开启Deep Stubs(代码改动最小)

给需要链式调用的Mock声明开启深度打桩,Mockk会自动复用链式调用中间节点的mock实例,允许多次访问:

// 给Notifier的Mock加上deepStubs = true参数
@MockK(deepStubs = true) private lateinit var notifier: Notifier

其余测试代码不需要改动,即可正常运行。这种方案适合链式层级多、中间节点不需要单独验证的场景,写起来更简洁。

方案3:链式打桩时绑定同一个mock实例

你也可以在打桩时直接把中间节点的返回指定为同一个mock,写法如下:

every { notifier.action } returns mockk {
  every { getSteps() } returns listOf(1,2,3)
  every { send() } returns 1
}

这种写法不需要额外声明Action的Mock变量,代码也比较紧凑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 00:18:03