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

Kotlin+Compose中ViewModel测试Mockk报错:Missing mocked calls问题

解决MockK测试ViewModel时的"Missing mocked calls"错误

错误原因分析

你遇到的Missing mocked calls inside every { ... } block错误,核心问题是错误地在every块中直接引用mock实例,而不是调用mock的方法或属性。MockK的every语法要求块内必须是对mock对象的方法/属性调用,直接写mock对象本身的写法完全不符合规则,导致MockK无法识别这是有效的mock调用,进而抛出异常。

看你代码里的这些无效写法:

every { mockProduct1 } returns product1
every { mockProduct2 } returns product2
every { mockGroupProduct1 } returns groupProduct1
every { mockGroupProduct2 } returns groupProduct1

修复步骤

1. 移除无效mock或修正mock行为

如果Product和GroupProduct是数据类,且测试中不需要模拟它们的复杂行为,直接使用真实实例即可,不需要mock,这会让测试逻辑更简洁:

// 直接创建真实数据实例,无需mock
val product1 = Product(id = 1, name = "Test 1")
val product2 = Product(id = 2, name = "Test 2")
val groupProduct1 = GroupProduct(product = product1, quantity = 5)
val groupProduct2 = GroupProduct(product = product2, quantity = 3)

如果确实需要mock这些类(比如它们包含需要模拟的方法),要针对具体方法或属性设置mock行为,例如:

val mockProduct1 = mockk<Product>()
// 模拟id属性的返回值
every { mockProduct1.id } returns 1
// 模拟name属性的返回值
every { mockProduct1.name } returns "Test 1"

2. 清理冗余mock

你的MyPantryViewModel构造函数只接收了mockGetGroupProductListUseCase和mockObserveAllProductsUseCase,代码中定义的mockGetGroupProductUseCase并未被使用,可以直接移除,减少不必要的代码复杂度。

3. 完整修复后的测试代码示例

class MyPantryViewModelTest {

    @Test
    fun `given viewmodel initialized when ui state observed then ui state is Empty`() {
        // 直接使用真实数据实例
        val product1 = Product(id = 1, name = "Test 1")
        val product2 = Product(id = 2, name = "Test 2")
        val expectedProductList = listOf(product1, product2)

        val groupProduct1 = GroupProduct(product = product1, quantity = 5)
        val groupProduct2 = GroupProduct(product = product2, quantity = 3)
        val groupsProduct = listOf(groupProduct1, groupProduct2)

        // Mock UseCase(这部分写法是正确的)
        val mockGetGroupProductListUseCase = mockk<GetGroupProductListUseCase>()
        every { mockGetGroupProductListUseCase.invoke(any()) } returns groupsProduct

        val mockObserveAllProductsUseCase = mockk<ObserveAllProductsUseCase>()
        every { mockObserveAllProductsUseCase.invoke() } returns flowOf(expectedProductList)

        // given
        val viewModel = MyPantryViewModel(mockGetGroupProductListUseCase, mockObserveAllProductsUseCase)

        // when
        val uiState = viewModel.uiState.value

        // then
        assertTrue(uiState is MyPantryUiState.Empty)
    }
}

额外注意事项

  • 如果用lazy初始化mock,要确保在every块之前已经触发初始化(比如提前调用一次mockProduct1),避免因mock未初始化导致的异常。
  • 遵循最小mock原则:只mock需要模拟行为或返回值的类,纯数据模型尽量用真实实例,降低测试的维护成本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 20:38:11