Android Kotlin单元测试Mockk报错:every块内缺少模拟调用
解决Android Kotlin单元测试Mockk匹配URL时的报错问题
报错原因
报错io.mockk.MockKException: Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock的核心问题:
Uri.Builder()是构造函数调用,不属于Uri类的静态方法范畴,mockkStatic(Uri::class)仅能mock静态方法,无法处理构造函数调用,因此直接写every { Uri.Builder() }会触发错误。- 实际业务代码中并未直接调用
Uri.Builder()构造函数,而是通过Uri.parse(url).buildUpon()获取Builder实例,原mock逻辑完全偏离了实际调用链路。
修正后的测试代码
1. 修正setUp方法
@Before fun setUp() { MockKAnnotations.init(this, relaxUnitFun = true) // 静态mock Uri类的parse方法 mockkStatic(Uri::class) }
2. 修正测试方法
@Test fun isParamTest() { // 创建mock的Uri和Uri.Builder实例 val mockUri = mockk<Uri>(relaxed = true) val mockBuilder = mockk<Uri.Builder>(relaxed = true) // 定义mock行为:Uri.parse返回mockUri every { Uri.parse(any()) } returns mockUri // 定义mockUri的buildUpon方法返回mockBuilder every { mockUri.buildUpon() } returns mockBuilder // 定义mockBuilder的build方法返回预期Uri(转换为字符串后匹配预期值) every { mockBuilder.build() } returns Uri.parse("https://test?test=testvalue") // 修正变量声明语法错误 val parameterKey = "test" val value = "testvalue" val inputURL = "https://test" val expected = "https://test?test=testvalue" val output = getWebURL(inputURL, parameterKey, value) assertThat(output).isEqualTo(expected) }
关键说明
- 针对
Uri.parse(url).buildUpon()的调用链路,需要分层mock:先让Uri.parse返回mock的Uri对象,再让该mock对象的buildUpon()方法返回mock的Builder对象。 - 如果需要验证
appendQueryParameter的调用逻辑,可以去掉Builder的relaxed = true,显式mock该方法:
这样可以验证参数是否正确传入。every { mockBuilder.appendQueryParameter(parameterKey, value) } returns mockBuilder
内容的提问来源于stack exchange,提问作者Android Dev
相关产品推荐
相关产品推荐

