Are there any good examples available yet using ne...
# multiplatform
j
Are there any good examples available yet using new Kotlinx Coroutines 1.6
runtTest
in
commonTest
tests? I have a basic test that tests flow which works if run for Android or JVM but for iOS target I'm getting following.
Copy code
UncompletedCoroutinesError: After waiting for 60000 ms, the test coroutine is not completing
m
I was also looking for a good example without success. But if it helps these tests work with Coroutines 1.6 with
runTest
in
commonTest
for
iOS
https://github.com/MartinRajniak/CatViewerDemo/blob/main/shared/src/commonTest/kotlin/eu/rajniak/cat/CatsTest.kt
I only found
runTest
docs https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/run-test.html that don't mention case when dispatcher is injected in production code (and should be replaced in tests).
j
Thanks, will take a look at that
m
I started using
kotlinx-coroutines-test
again after I read that in Coroutines 1.6 they added
kotlinx-coroutines-test
 with the new reworked API and multiplatform support
Switched in this commit https://github.com/MartinRajniak/CatViewerDemo/commit/5f6ba59489f306515ed59a719f30e0fbc04bf9ff#diff-7907192102e6f5b21406[…]c38ca72dbd8f450bca381e762
j
fwiw this is the test I'm trying to run....I'm suspecting I might need to add some specific dispatcher related plumbing for it to work for iOS https://github.com/joreilly/StarWars/blob/main/shared/src/commonTest/kotlin/dev/johnoreilly/starwars/shared/StarWarsRepositoryTest.kt
m
Isn't it only coincidence that it failed on iOS? I mean if it was a race condition then the fact that it failed on specific platform would not be a clue 🙂 (then again you probably tried it multiple times)
According to my understanding, this exception occurs when you are using a different dispatcher
https://stackoverflow.com/questions/61224047/unit-testing-coroutines-runblockingtest-this-job-has-not-completed-yet/67897542#67897542 In StarWarsRepository you are using
withContext(Dispatchers.Default)
I would assume you have to replace that with
TestScope
in tests (see the quote before).
Now that 
runTest
 works properly with asynchronous completions, 
runBlocking
 is only occasionally useful. As is, most uses of 
runBlocking
 in tests come from the need to interact with dispatchers that execute on other threads, like 
<http://Dispatchers.IO|Dispatchers.IO>
 or 
Dispatchers.Default
.
https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-test/MIGRATION.md#replace-runblocking-with-runtest
Injecting dispatcher worked for me. The main point is to make sure you are using the same test dispatcher instance in the block inside 
runBlockingTest { }
.
https://github.com/Kotlin/kotlinx.coroutines/issues/1204#issuecomment-857354670
For example, here they talk about how to do it to support skipping delays when
withContext
is used https://github.com/Kotlin/kotlinx.coroutines/tree/master/kotlinx-coroutines-test#virtual-time-support-with-other-dispatchers
j
I actually switched over in that repo after that to use an Apollo specific runTest and working ok now....needed seemingly due to particular thread switcing that Apollo is doing right now
Needed in particular when using Kotlin/Native
m
glad to hear that you figured it out 🙂 I thought that some external dependency might be causing issues I read somewhere in the documentation that they discuss what to do if you can't inject scope because it is used in external dependency I can't remember what is the proposed solution, but I would assume that: • either library plays along (like you mention with Apollo), • or library only uses suspend functions and client handles dispatchers,
j
I think also that move to new memory model will also potentially simplify some of these interactions
m
true - might be another variable 🤯 I am already using new memory model with coroutines 1.6
j
btw re. the
withContext
code, that isn't coming in to play in this particular test but agreed that should probably inject dispatcher for that