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

使用MockK测试时Mock Uri报错Can't Find Stub如何解决?

问题原因
  • 你没有正确mock Models类的静态成员:Models.APPOINTMENT.contentUri是Models类的成员属性,不属于Uri类的静态方法范畴,你当前只调用了mockkStatic(Uri::class),完全没有对Models类做mock配置,MockK自然找不到对应的stub规则。
  • 额外mock Uri类静态方法但没有配置对应stub:你mock了Uri的静态类后,调用Uri.parse、Uri.withAppendedPath时没有配置对应的返回规则,这两个方法返回的是临时生成的未stub的mock Uri对象,进一步触发了找不到stub的报错。
解决方案

根据你的测试环境可以任选以下两种方案:

方案一:使用Robolectric(推荐,可直接调用安卓系统API真实实现)

引入Robolectric测试框架,直接调用真实的Uri工具方法,仅mock需要的Models类成员即可,修改后代码如下:

import org.robolectric.RobolectricTestRunner
import org.junit.runner.RunWith

@RunWith(RobolectricTestRunner::class)
class GetNavigationModelTest {

    @MockK
    lateinit var mockContentResolver: ContentResolver

    private val useCaseUnderTest = GetNavigationModel()

    @Before
    fun setup() {
        MockKAnnotations.init(this)
        // 针对Models类做静态mock,若Models是Kotlin object类则改用mockkObject(Models)
        mockkStatic(Models::class)
        // 有Robolectric支持可直接调用Uri的真实方法
        val testUri = Uri.withAppendedPath(Uri.parse(BASE_URI), UUID)
        every { Models.APPOINTMENT.contentUri } returns testUri
        // 补充contentResolver query方法的stub,避免后续调用时报错
        every { 
            mockContentResolver.query(eq(testUri), any(), any(), any(), any()) 
        } returns mockk(relaxed = true)
    }

    @Test
    fun myTest() {
        useCaseUnderTest.invoke(mockContentResolver, UUID)
        assert(true)
    }

    @After
    fun teardown() {
        // 清除静态mock,避免污染其他测试用例
        unmockkStatic(Models::class)
    }

    companion object {
        private const val BASE_URI = "content://com.example.provider"
        private const val UUID = "appointment"
    }
}

方案二:无需Robolectric,直接mock Uri实例

如果不想引入Robolectric,完全不需要mock Uri的静态方法,直接构造mock Uri实例赋值即可:

class GetNavigationModelTest {

    @MockK
    lateinit var mockContentResolver: ContentResolver
    @MockK
    lateinit var mockUri: Uri

    private val useCaseUnderTest = GetNavigationModel()

    @Before
    fun setup() {
        MockKAnnotations.init(this)
        // 针对Models类做静态mock,若Models是Kotlin object类则改用mockkObject(Models)
        mockkStatic(Models::class)
        every { Models.APPOINTMENT.contentUri } returns mockUri
        // 补充contentResolver query方法的stub
        every { 
            mockContentResolver.query(eq(mockUri), any(), any(), any(), any()) 
        } returns mockk(relaxed = true)
    }

    @Test
    fun myTest() {
        useCaseUnderTest.invoke(mockContentResolver, UUID)
        assert(true)
    }

    @After
    fun teardown() {
        unmockkStatic(Models::class)
    }

    companion object {
        private const val UUID = "appointment"
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 07:15:04