Search code examples
androidkotlintestingviewmodelmockk

Cannot mock in test of ViewModel. (Kotlin, Compose)


I have a problem with mocks in test of view model. I have error on every compilation:

Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock
io.mockk.MockKException: Missing mocked calls inside every { ... } block: make sure the object inside the block is a mock

I cannot make the mocks to test the behavior of viewmodel.

class MyPantryViewModelTest {

    @Test
    fun `given viewmodel initialized when ui state observed then ui state is Empty`() {
        val mockProduct1 by lazy { mockk<Product>() }
        val mockProduct2 = mockk<Product>()
        val mockGroupProduct1 = mockk<GroupProduct>()
        val mockGroupProduct2 = mockk<GroupProduct>()

        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 = mockProduct1, quantity = 5)
        val groupProduct2 = GroupProduct(product = mockProduct2, quantity = 3)
        val groupsProduct = listOf(groupProduct1, groupProduct2)

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

        val mockGetGroupProductListUseCase = mockk<GetGroupProductListUseCase>()
        every { mockGetGroupProductListUseCase.invoke(any()) } returns groupsProduct

        val mockGetGroupProductUseCase = mockk<GetGroupProductUseCase>()
        every { mockGetGroupProductUseCase.invoke(any(), any()) } returns groupProduct1

        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)
    }
}

I tried to mock classes in my view model test, but every time I receiving the error like above.


Solution

  • You don't need to mock your product if you have fake products created. You have to use every with a function call. For example:

    every { productProducer.getNewProduct() } returns product1
    

    Just remove the four every for your mockProducts and mockGroupProducts and your code should work.