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

Mockito Kotlin:如何验证作为另一个类构造参数的类的方法调用?

问题分析与解决方案

你的核心问题是测试中ClassA依赖的ClassB实例,和你用来验证的ClassB Mock实例不是同一个:

  • 原测试类通过构造函数注入ClassA时,Spring容器可能已经用ClassB的实际实例完成了ClassA的初始化;
  • 之后通过@MockBean注册的ClassB Mock实例,并没有替换掉ClassA内部持有的那个实际实例,所以验证时自然找不到调用记录。

可行的解决方案

方案1:让Spring用Mock实例自动注入ClassA(集成测试场景)

用@SpringBootTest启动测试上下文,通过@MockBean替换容器中的ClassB实例,再自动注入ClassA——此时ClassA内部的ClassB就是Mock实例,和你测试代码中持有的是同一个:

@SpringBootTest
class Test {
    @Autowired
    private lateinit var classA: ClassA

    @MockBean
    private lateinit var classB: ClassB

    @Test
    fun testSomething() {
        classA.someMethod()

        verify(classB, times(1)).anotherMethod(arg1, arg2)
    }
}

方案2:手动构造ClassA并传入Mock实例(单元测试场景)

如果不需要完整的Spring上下文,直接手动创建ClassB的Mock实例,再传给ClassA的构造函数,避免容器注入的混乱:

class Test {
    private val classBMock: ClassB = mock()
    private val classA: ClassA = ClassA(classBMock)

    @Test
    fun testSomething() {
        classA.someMethod()

        verify(classBMock, times(1)).anotherMethod(arg1, arg2)
    }
}

关于“验证实际实例方法调用”的补充

如果确实需要验证ClassB实际实例的调用,只能把实际实例包装成Spy(Mockito的监控对象),但这种方式不推荐,因为会破坏封装且可能引入副作用:

  1. 先获取ClassB的实际实例;
  2. 把它包装成Spy;
  3. 替换ClassA内部的ClassB实例(需要ClassA的classB字段是可修改的,或者用反射强行替换);
  4. 最后对Spy实例进行验证。

示例代码(需注意反射的局限性):

@SpringBootTest
class Test {
    @Autowired
    private lateinit var classA: ClassA

    @Autowired
    private lateinit var realClassB: ClassB

    private lateinit var spyClassB: ClassB

    @BeforeEach
    fun setUp() {
        spyClassB = spy(realClassB)
        // 假设ClassA的classB是var类型,直接替换
        classA.classB = spyClassB
        // 如果是val类型,需要用反射:
        // val field = ClassA::class.java.getDeclaredField("classB")
        // field.isAccessible = true
        // field.set(classA, spyClassB)
    }

    @Test
    fun testSomething() {
        classA.someMethod()

        verify(spyClassB, times(1)).anotherMethod(arg1, arg2)
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 12:03:33