MockK模拟失效:调用原始类而非模拟结果的测试问题
问题根源
你猜的没错——B类内部直接实例化了A类,导致测试中创建的mockk<A>()对象和B里的private val a = A()完全是两个独立的实例。B的amend()方法只会调用自己内部创建的原始A实例,根本不会用到你在测试里定义的mock对象,所以MockK自然不生效。
解决方案
方案1:重构B类,使用依赖注入(推荐)
这是最规范的做法,让B类不再硬编码创建A,而是通过构造函数接收A的实例,测试时即可传入mock对象:
修改后的B类代码:
class A { fun getName() = "Name" } class B(private val a: A) { // 构造函数注入A实例 fun amend(): String { return "${a.getName()}-BName" } }
对应的测试代码:
@Test fun amendTest() { // 创建A的mock实例 val mockA = mockk<A>() // 指定mock行为:调用getName返回空字符串 every { mockA.getName() } returns "" // 将mock实例传入B的构造函数 val b = B(mockA) val newName = b.amend() // 验证mock的getName方法被调用 verify { mockA.getName() } // 断言结果符合预期 Truth.assertThat(newName).isEqualTo("-BName") }
方案2:MockK构造函数(适合无法修改原代码的场景)
如果因为历史原因不能修改B类代码,可以用MockK的mockkConstructor拦截A类的构造函数,让B内部创建的A实例自动变成mock对象:
测试代码如下:
@Test fun amendTestWithConstructorMock() { // 拦截A类的构造函数,所有新创建的A实例都是mock mockkConstructor(A::class) // 设置所有A实例的getName返回空字符串 every { anyConstructed<A>().getName() } returns "" val b = B() val newName = b.amend() verify { anyConstructed<A>().getName() } Truth.assertThat(newName).isEqualTo("-BName") // 清理构造函数mock,避免影响其他测试用例 unmockkConstructor(A::class) }
注意:这种方式会影响所有测试中A类的实例化,务必在测试完成后用unmockkConstructor清理,防止产生副作用。
内容的提问来源于stack exchange,提问作者Erick
相关产品推荐
相关产品推荐

