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

如何使用MockK测试依赖Dagger注入的Kotlin类A?

问题描述

我是依赖注入(Dagger)领域的新手,跟着各类教程学习后帮助不大。现有类A、B、C的代码如下:

class C @Inject constructor() {
    fun doIt(i: Int): Int{
        return i*100
    }
}

class B {
    @Inject
    constructor()

    fun doIt(i: Int): Int{
        return i*10
    }
}


class A @Inject constructor(val b: B) {  // (primary) constructor injection

    @Inject // field injection
    lateinit var c: C // late = after init/constructor

    fun doIt(i: Int): Int{
        return c.doIt(i) + b.doIt(i) + 1
    }

}

尝试用MockK对类A进行单元测试,但没搞懂运作原理,测试代码如下:

internal class ExampleUnitTest2 {
    @MockK
    lateinit var c: C

    @MockK
    lateinit var b: B

    @Before
    fun setUp() = MockKAnnotations.init(this)

    @Test
    fun myTest() {
        coEvery { c.doIt(5) } returns 500
        coEvery { b.doIt(5) } returns 50

        val a = A(b)
        assertEquals(a.doIt(5), 555)
    }
}
核心问题

测试代码存在两个关键问题:

  1. 未初始化类A的c字段:A中的c是字段注入的lateinit属性,创建A实例时仅传入了构造注入的b,未给c赋值,调用doIt时会抛出UninitializedPropertyAccessException。
  2. 错误使用coEvery:coEvery用于Mock挂起函数,而doIt是普通同步函数,应使用every。
解决方法

方案1:手动注入Mock实例

创建A实例后,直接给c字段赋值Mock对象:

internal class ExampleUnitTest2 {
    @MockK
    lateinit var c: C

    @MockK
    lateinit var b: B

    @Before
    fun setUp() = MockKAnnotations.init(this)

    @Test
    fun myTest() {
        // 用every替代coEvery,适配同步函数
        every { c.doIt(5) } returns 500
        every { b.doIt(5) } returns 50

        val a = A(b)
        // 手动注入c的Mock实例
        a.c = c

        // 预期值为500+50+1=551,原测试用例的555计算错误
        assertEquals(a.doIt(5), 551)
    }
}

方案2:用@InjectMockKs自动注入

MockK的@InjectMockKs注解可自动将@MockK标记的实例注入到被测类的构造参数和字段中,无需手动处理:

internal class ExampleUnitTest2 {
    @MockK
    lateinit var c: C

    @MockK
    lateinit var b: B

    // 自动注入Mock对象到A实例
    @InjectMockKs
    lateinit var a: A

    @Before
    fun setUp() = MockKAnnotations.init(this)

    @Test
    fun myTest() {
        every { c.doIt(5) } returns 500
        every { b.doIt(5) } returns 50

        assertEquals(a.doIt(5), 551)
    }
}

说明

  • @InjectMockKs会自动处理两种注入方式:构造注入的参数(如A的b)、字段注入的属性(如A的c),无需手动创建A实例。
  • 注意修正预期值:原测试用例中的555是计算错误,正确结果应为500+50+1=551。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 22:17:47