Let's consider the following code:
class UseCase() {
suspend operator fun invoke(param1: String) = Unit
}
class MyViewModel @Inject constructor(val useCase: UseCase) {
fun init() {
viewModelScope.launch {
useCase("inputParam")
}
}
}
class MyViewModelTest() {
@MockK
private lateinit var useCase: UseCase
private lateinit var viewModel: MyViewModel
@BeforeTest
private setUp() {
MockKAnnotations.init(this)
viewModel = MyViewModel(useCase)
}
@Test
fun `Test case 1`() {
viewModel.init()
coVerify { useCase("inputParam") }
confirmVerified(useCase)
}
@Test
fun `Test case 2 where I need to override the useCase result`() {
coEvery { useCase(any()) } throws Exception("Unexpected error")
try {
viewModel.init()
} catch(e: Exception) {
assertEquals("Unexpected error", e.message)
}
}
}
The error you would get:
io.mockk.MockKException: no answer found for: UseCase(#1).invoke("inputParam", continuation {})
Read more around the issue here: mockk/mockk#288
The workaround is two part:
- Most cases where you only need one mock to return the same output, the solution is to simply move it to the @BeforeTest setup phase of your unit test, where this issue doesn't come up
- If you need to test different outputs, you would need to call
coVerify
again, so to avoid this problem, you have to reinitialize your class with this new mock and clear the mock beforehand
class MyViewModelTest() {
@MockK
private lateinit var useCase: UseCase
private lateinit var viewModel: MyViewModel
@BeforeTest
private setUp() {
MockKAnnotations.init(this)
coEvery { useCase(any()) } coAnswers { Unit } // Moving it to BeforeTest does help alleviate the issue
viewModel = MyViewModel(useCase)
}
@Test
fun `Test case 1`() {
viewModel.init()
coVerify { useCase("inputParam") }
confirmVerified(useCase)
}
@Test
fun `Test case 2 where I need to override the useCase result`() {
clearMocks(useCase) // Clear mock here
coEvery { useCase(any()) } throws Exception("Unexpected error")
viewModel = MyViewModel(useCase) // need to reinstantiate
try {
viewModel.init()
} catch(e: Exception) {
assertEquals("Unexpected error", e.message)
}
}
}