Test passes for 'runBlocking' but fails for 'runBlockingTest'
See original GitHub issueThe test below passes when runBlocking
is used but fails with runBlockingTest
.
sealed class Event {
data class A(val id: Long) : Event()
data class B(val id: Long) : Event()
}
class Test {
@Test fun blocking() = runBlocking {
val events = flowOf(Event.A(0), Event.B(0)).broadcastIn(this).asFlow()
val a = events.filterIsInstance<Event.A>().map { "$it" }
val b = events.filterIsInstance<Event.B>().map { "$it" }
val strings = flowOf(a, b).flattenMerge().toList()
Assert.assertEquals(strings, listOf(Event.A(0), Event.B(0)).map { "$it" })
}
@Test fun blockingTest() = runBlockingTest {
val events = flowOf(Event.A(0), Event.B(0)).broadcastIn(this).asFlow()
val a = events.filterIsInstance<Event.A>().map { "$it" }
val b = events.filterIsInstance<Event.B>().map { "$it" }
val strings = flowOf(a, b).flattenMerge().toList()
Assert.assertEquals(strings, listOf(Event.A(0), Event.B(0)).map { "$it" })
}
}
Events are missing from the expected result.
java.lang.AssertionError:
Expected :[A(id=0)]
Actual :[A(id=0), B(id=0)]
Kotlin: 1.3.50
.
Coroutines: 1.3.2
.
Issue Analytics
- State:
- Created 4 years ago
- Reactions:10
- Comments:10 (5 by maintainers)
Top Results From Across the Web
Unit testing coroutines runBlockingTest: This job has not ...
I tried to replace runBlockingTest with runBlocking but the test seems to wait in an infinite loop. Can someone help me with this...
Read more >Unit Testing with Kotlin Coroutines: The Android Way - Medium
We can mitigate the problem by using the runBlocking() function. This function runs a new Coroutine and blocks the current thread interruptibly ...
Read more >runBlockingTest - Kotlin
runBlockingTest ... Executes a testBody inside an immediate execution dispatcher. This method is deprecated in favor of runTest. Please see the migration guide ......
Read more >Testing Kotlin Coroutines - Kt. Academy
How we test Kotlin Coroutines, including common Android and backend cases. ... we practically need nothing else but runBlocking and classic tools for ......
Read more >Say goodbye to Flakiness: Testing Coroutines and Kotlin ...
While runBlocking will wait for the amount of the delay , runBlockingTest will skip past any ... Run the test again and you...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Are there any news or a timeline for this? Removing delays in tests via RunBlockingTest would be very helpful, but only if it works reliably without a lot of extra coding.
Yes, that’s a common complaint. The typical solution is to wrap all references up into a single injectable object like so:
A different solution is in the works for #1365 , where you’ll be able to use
Dispatchers.setDefault(...)
to manipulate that singleton in lieu of all the injection, but now you’re manipulating a shared state in your testing.You can do things to mitigate this issue, such as only specifying the dispatcher when it’s really necessary (for instance immediately before doing I/O in a repository). Typically, you shouldn’t need to specify the dispatcher as the main thread is typically capable of much more than we give it credit for. Also, if you’re using a third party library with coroutine support for I/O, such as Room or Retrofit, they already use their own dispatchers internally, so switching before calling a suspend function in their library is just wasteful.
Not to plug, but a final option would be my not-quite-complete little library DispatcherProvider, which uses the
CoroutineContext
itself to hold the interface described above. This way, the dispatchers are set upon creation of aCoroutineScope
and are accessible from any coroutine or suspend function via thecoroutineContext
property.