https://kotlinlang.org logo
#coroutines
Title
# coroutines
t

Tom Yuval

08/31/2022, 1:56 PM
I’m running some tests that call
suspend
functions, so I’m using
kotlinx.coroutines.test.runTest
. This has the useful feature of skipping `delay`s and simulating actual scheduling with virtual time, which is super useful as it allows the tests to run fast, and one can also control the order of execution of various parts of different coroutines very delicately. However, I have a very specific use case where functions under test use `delay`s, and I actually want the `delay`s to execute for real, just like they would in production (this shouldn’t normally be required in pure unit tests, but is necessary in my case as the functions I’m testing interact with other systems). Is there a way to do that?
m

mkrussel

08/31/2022, 1:58 PM
You could use
runBlocking
instead of
runTest
if you really want to delay. But if you want to control the delays instead of actually delaying, you may want to look at https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-test/kotlinx.coroutines.test/-standard-test-dispatcher.html
t

Tom Yuval

08/31/2022, 2:26 PM
Thanks for your message, @mkrussel. I can’t use
runBlocking
because, at least in some cases, I’m targeting JS…
Also, I’m not sure what you mean by “control the delays instead of actually delaying”, but I think I want to actually delay. I can try and see though if it works; how would I use this
StandardTestDispatcher
? Currently my code look something like:
Copy code
@Test
fun testSomething() = runTest {
    performTests()
}
How do I rewrite that to use
StandardTestDispatcher
?
m

mkrussel

08/31/2022, 4:59 PM
I think you need to set that as the main dispatcher and then runTest will use its scheduler. You can then use its scheduler to control the virtual time (control when a delay finishes, instead of waiting for it to actually finish). This way you can test delays without actually delaying. See controlling virtual time https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-test/
e

ephemient

08/31/2022, 5:01 PM
on JS you should be able to write
Copy code
@Test
suspend fun testSomething() {
}
or
Copy code
@Test
fun testSomething() = GlobalScope.promise {
}
and get real delays
t

Tom Yuval

09/01/2022, 7:21 AM
@mkrussel: thanks, but my point was that I do want the actual delays. @ephemient: 1.
@Test suspend fun
does not seem to work (it fails to even compile:
Unsupported [suspend test functions]
). 2.
GlobalScope.promise
seems to do exactly what I need – thanks! 👍
e

ephemient

09/01/2022, 4:23 PM
huh, I thought K/JS had desugaring for the first case. I guess not - but glad the second worked. if you want, you can create your own wrappers, e.g.
Copy code
// common
expect fun runRealTest(context: CoroutineContext = EmptyCoroutineContext, testBody: suspend () -> Unit): TestResult
// JS
actual fun runRealTest(context: CoroutineContext, testBody: suspend () -> Unit) = GlobalScope.promise(context) { testBody() }
// other
actual fun runRealTest(context: CoroutineContext, testBody: suspend () -> Unit) = runBlocking(context) { testBody() }
31 Views