gergo
02/01/2019, 5:39 PMwithoutclass
02/01/2019, 5:50 PMlaunch
is running in that scope instead of the runBlocking
scope in your test. I also don’t see any code where you’re providing the coroutineContext in your ViewModel in order to satisfy CoroutineScopeghedeon
02/01/2019, 5:51 PMgergo
02/01/2019, 5:58 PMoverride val coroutineContext: CoroutineContext
this line provides the coroutineContext for the Scope implementation.
So should I inject the runBlocking's CoroutineScope into the ViewModel then?ghedeon
02/01/2019, 6:04 PMghedeon
02/01/2019, 6:04 PMwithoutclass
02/01/2019, 6:05 PMghedeon
02/01/2019, 6:05 PMstreetsofboston
02/01/2019, 6:16 PMrunBlocking {
viewModel.start().join()
}
...
fun start() : Job {
return launch{
foo.value = "alma"
}
}
streetsofboston
02/01/2019, 6:17 PMstart()
launches a Job and returns immediately. On occasion, if you try often enough, a call to foo.value = "alma"
could slip through and gets executed, but sometimes, it may not.gergo
02/01/2019, 6:22 PMwithoutclass
02/01/2019, 6:27 PMasync
, and use a getter off the viewmodel wait for the value to return, or have the viewmodel return a deferred and let the calling code wait for the value.
You could also use a channel for communicating values from the ViewModel, then the calling code will wait for the value to be emittedstreetsofboston
02/01/2019, 6:41 PMTestCoroutineContext
. Provide an instance of this to your ViewModel and call triggerActions
on it.
val testCoroutineContext= TestCoroutineContext()
val viewModel = ViewModel(testCoroutineContext)
viewModel.start()
testCoroutineContext.triggerActions()
assertEquals("alma", viewModel.foo.value)
(no repeat
, no runBlocking
in your test)gergo
02/01/2019, 6:45 PMghedeon
02/01/2019, 6:59 PM