azabost
05/14/2022, 12:49 AMrunTest
behavior that makes it run all the delays at the end of the test body. I think I saw it mentioned somewhere, maybe in some GitHub issue, but I can’t find any mentions in the documentation regarding that behavior.
Example:
private val testCoroutineScheduler = TestCoroutineScheduler()
private val standardTestDispatcher = StandardTestDispatcher(testCoroutineScheduler)
@Test
fun `should execute the coroutine with delays`() = runTest(standardTestDispatcher) {
var iterations = 0
val job = launch {
while(isActive) {
println("iteration")
iterations++
delay(10)
}
}
iterations.shouldEqual(0) // this is an assertion
runCurrent()
iterations.shouldEqual(1)
advanceTimeBy(5)
iterations.shouldEqual(1)
advanceTimeBy(5)
iterations.shouldEqual(1)
runCurrent()
iterations.shouldEqual(2)
advanceTimeBy(10)
runCurrent()
iterations.shouldEqual(3)
job.cancel()
}
If I remove job.cancel()
at the end, the test is never going to finish and I’m going to be flooded by the println
invocations.
That behavior is quite problematic for me sometimes and that’s why I’m trying to understand it better.
There are some cases where I:
• want to control the scheduler to see how many times something periodical happened
• want the test to finish despite the lack of direct access for the launched coroutine containing the delay
For example:
private val testCoroutineScheduler = TestCoroutineScheduler()
private val standardTestDispatcher = StandardTestDispatcher(testCoroutineScheduler)
class Refresher(scope: CoroutineScope, refreshingDispatcher: CoroutineDispatcher) {
var refreshCount = 0
init {
scope.launch(refreshingDispatcher) {
while (isActive) {
refreshCount++
delay(10)
}
}
}
}
@Test
fun `refreshing should work`() = runTest(standardTestDispatcher) {
val refresher = Refresher(this, standardTestDispatcher)
refresher.refreshCount.shouldEqual(0)
runCurrent()
refresher.refreshCount.shouldEqual(1)
advanceTimeBy(15)
refresher.refreshCount.shouldEqual(2)
// this test never ends and I can't cancel the launched coroutine
}
I can make it work by removing runTest
but I’m simply not sure if this is what I should do in this scenario.
@Test
fun `refreshing should work`() {
val refresher = Refresher(CoroutineScope(standardTestDispatcher), standardTestDispatcher)
refresher.refreshCount.shouldEqual(0)
testCoroutineScheduler.runCurrent()
refresher.refreshCount.shouldEqual(1)
testCoroutineScheduler.advanceTimeBy(15)
refresher.refreshCount.shouldEqual(2)
}
Any advices?jw
05/14/2022, 1:18 AMazabost
05/23/2022, 10:22 AMrunTest {
val childScope = CoroutineScope(coroutineContext + Job(coroutineContext[Job]))
// ... use childScope here ...
childScope.cancel()
}
or something else?azabost
05/23/2022, 5:41 PMrunTest
?