AKlam
01/31/2022, 2:36 PMAKlam
01/31/2022, 2:45 PMtestImplementation("io.mockk:mockk:1.12.2")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.0")
bezrukov
01/31/2022, 2:46 PMAKlam
01/31/2022, 2:51 PMbezrukov
01/31/2022, 2:52 PMval scope by lazy { CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) }
val viewModel by lazy { .... }
.....
fun `test vm`() = runTest {
vm.push()
runCurrent()
verify...
scope.cancel()
}
bezrukov
01/31/2022, 2:55 PMAKlam
01/31/2022, 3:13 PMsample()
somehow blocks runTest
and preventing it from terminating 🤔Nick Allen
01/31/2022, 10:14 PMThere is no problem testing infinite coroutine as you can see in attached fileYour code also passes just fine if
push
launches a job that throws an exception after emitting. The problem is there, your test code just isn't detecting it.
IMHOSample creates a repeating timer, so even though your test is poorly setup, it's still able to detect that something is scheduled so you've leaked a coroutine. Give your tested code a CoroutineScope that is connected to your TestScope. That way it can detect infinite coroutines and also other errors. If you have infinite coroutines, give your tested code a child scope and cancel that. And if you don't use Main, then you don't need to set main. Here's an example:somehow blockssample()
and preventing it from terminating 🤔runTest
class SomeTest {
private val testScope = TestScope()
val viewModelScope = testScope + Job(testScope.coroutineContext.job)
val viewModel = SomeViewModel(viewModelScope)
@Test
fun `test vm`() = testScope.runTest {
viewModel.push()
runCurrent()
viewModelScope.cancel()
verify(exactly = 1) { viewModel.drop() }
}
}
And if you really are checking if viewModel.someMethod()
causes viewModel.someOtherMethod()
to be called (as opposed to it just being for the example), I would suggest you re-evaluate how you are writing your tests. I suspect either your class should be split up or your tests are fragile and will constantly break even just from changing minor details of the implementation. Do you really want to rewrite unit tests even for changes that have no behavior change from a public API perspective?