Android单元测试Mockk报错:Missing calls inside every { ... } block
问题分析与解决方案
错误原因
MockK Missing calls异常:
testParsedResponse是普通String实例,并非MockK创建的mock对象,因此every { testParsedResponse.fromJson<TaskListData>() }的写法无效——MockK只能拦截mock对象的方法调用,无法处理普通对象的扩展函数调用,导致Missing calls inside every { ... } block错误。空指针异常:
单元测试运行在JVM环境,没有完整的Android系统上下文支持。logback初始化时尝试调用Android系统相关API获取外部存储路径,而mock的Context无法提供有效实现,引发NPE。
修复步骤
1. 修复MockK的方法拦截问题
有两种可行方案:
方案A:构造有效JSON字符串,让解析逻辑自然执行
直接让parseJsonFile返回能被fromJson正确解析为TaskListData的JSON字符串,无需mock扩展函数:
@Test fun `fetchTasks returns expected response`() = runTest { // given // 匹配TaskListData结构的有效JSON val validTaskJson = """{"tasks": []}""" val fileName = "tasks.json" every { context.parseJsonFile(fileName) } returns validTaskJson // when val actualResponse = fetchTasksRepositoryImpl.fetchTasks() // then assertTrue(actualResponse is ApiResponse.Success) assertEquals((actualResponse as ApiResponse.Success).data.tasks, emptyList()) }
方案B:用mockkStaticMock扩展函数
如果需要单独验证fromJson的调用逻辑,可使用mockkStatic拦截顶层扩展函数:
@Test fun `fetchTasks returns expected response`() = runTest { // given val testParsedResponse = "任意字符串" val fileName = "tasks.json" val mockTaskData = TaskListData(listOf()) every { context.parseJsonFile(fileName) } returns testParsedResponse // 替换为你的fromJson扩展函数所在的包路径 mockkStatic("com.your.app.package.JsonExtensionsKt") every { testParsedResponse.fromJson<TaskListData>() } returns mockTaskData // when val actualResponse = fetchTasksRepositoryImpl.fetchTasks() // then assertTrue(actualResponse is ApiResponse.Success) assertEquals((actualResponse as ApiResponse.Success).data, mockTaskData) // 清理mock unmockkStatic("com.your.app.package.JsonExtensionsKt") }
2. 解决logback引发的NPE
在模块级build.gradle中排除MockK依赖中的logback组件,避免Android相关初始化逻辑:
// Groovy DSL testImplementation("io.mockk:mockk:1.13.8") { exclude group: "ch.qos.logback" }
// Kotlin DSL testImplementation("io.mockk:mockk:1.13.8") { exclude(group = "ch.qos.logback") }
或者在测试类中提前配置logback避免无效初始化:
@BeforeAll fun setupTestEnvironment() { System.setProperty("logback.configurationFile", "null") }
内容的提问来源于stack exchange,提问作者Imtiaz Dipto
相关产品推荐
相关产品推荐

