Hello, I’m trying to validate my Google findings. ...
# coroutines
r
Hello, I’m trying to validate my Google findings. Is it accurate to say that the best (only?) approach to making this testable is to have a dispatcher provider that masks which
Dispatcher
is provided during testing?
s
No. If you
launch
it on the CoroutineScope that is or is a child of your runBlocking's or runBlockingTest's CoroutineScope, your test won't finish until all you asynchronous code has finished (with good result or an exception). However, if you have delays, timeouts, etc and you don't want to have long running tests, or when you launch async code from different CoroutineScopes, then using runBlockingTest with its TestCoroutineDispatcher is of great use, since you can fast-forward through time.
Of course, the best approach may still be to make the dispatcher injectable, providing it. Just in case you do, in the future, add delays, timeouts, etc.
j
Currently with
runBlockingTest
being not multiplatform and so buggy... I think there is no way to testing properly without injecting it 😕
s
For most you can just use runBlocking....
j
not same, runBlocking doesn't have the test dispatcher
s
But most of the time you don't need that dispatcher.... just let the runBlocking run its course.
j
so you are forced to inject at least the coroutineContext if you are testing things like stateflow
yeah, but should be great I have no need to inject it in viewmodels for example for testing the stateflow and so on
s
Yup; with stateflow, you probably use different coroutinescope to launch/start them. Then a simple runBlocking may not be sufficient
But for testing plain suspend funs, cold flows, etc, runBlocking is often enough.
j
yeah, because stateflow conflates, I need the test dispatcher to resume/pause
and with runBlockingTest, it just fail (issue I shared above)
r
There’s one detail I omitted on line 3 that may make a difference. The line actually reads
customScope.launch(<http://Dispatchers.IO|Dispatchers.IO>)
@streetsofboston If you’ll notice, I am actually using
runBlockingTest
in my test, however the launch block appears to not have time to complete before I try to verify the results.
I was hoping that
runBlockingTest
would actually await completion of the block, but it seems that because the scope is custom, I won’t be able to rely on that
perhaps the method itself should be suspending instead of restricting the single piece of processing to a different Job?
m
You could move the verification code outside the
runBlockingTest
so that the launch has finished before you do your asserting. Even though most samples show
fun test() = runBlocking
, you can place the
runBlocking
inside the body of a normal test method.