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

如何使用Mockk测试Spy的init块是否调用指定方法

问题原因

当你调用spyk<Example>()时,MockK的执行逻辑是:先调用真实构造函数创建Example实例(此时init块立即执行,调用了test()),之后才将这个实例包装成Spy代理。也就是说,init块里的test()调用发生在Spy代理生效之前,完全绕过了MockK的调用拦截器,所以verify无法检测到这次调用。

第一个测试中,init块触发的test()没被统计,只有testWrapper()触发的那一次被记录,因此verify(exactly = 1)能通过;而实际test()执行了两次,但只有代理生效后的那次被计数。

解决方案

方案1:使用@SpyK注解初始化Spy

通过MockKAnnotations配合@SpyK注解,MockK会在对象初始化之前就创建好代理,这样init块中的方法调用会被代理捕获并记录。

修改后的测试代码:

class ExampleTest {
    @SpyK(recordPrivateCalls = true)
    lateinit var instance: Example

    @BeforeEach
    fun setup() {
        MockKAnnotations.init(this)
    }

    @Test
    fun `testWrapper should call test`() {
        instance.testWrapper()
        verify(exactly = 2) { instance.test() } // init调用1次 + testWrapper调用1次
    }

    @Test
    fun `init should call test`() {
        verify(exactly = 1) { instance.test() }
    }
}

方案2:手动控制初始化时机(无需修改原代码)

用mockk创建对象并指定默认调用真实方法,再通过反射触发构造过程,确保调用被MockK拦截:

class ExampleTest {
    @Test
    fun `init should call test`() {
        val instance = mockk<Example>(relaxed = true) {
            every { anyConstructed<Example>() } answers { callRealMethod() }
        }

        Example::class.java.getDeclaredConstructor().newInstance()
        
        verify(exactly = 1) { instance.test() }
    }
}

方案3:重构原代码(推荐)

如果允许修改业务代码,将init块逻辑提取到单独方法,让测试更直观:

class Example {
    init {
        initLogic()
    }

    private fun initLogic() {
        test()
    }

    fun testWrapper() = test()

    fun test() = println("test was called!")
}

测试时可以直接验证私有方法或目标方法:

@Test
fun `init should trigger test via initLogic`() {
    val instance = spyk<Example>(recordPrivateCalls = true)
    // 验证私有初始化方法被调用
    verifyPrivate(instance) { invoke("initLogic") }
    // 或者直接验证test()的调用次数
    verify(exactly = 1) { instance.test() }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 17:44:51