https://kotlinlang.org logo
Title
l

Lukasz Kalnik

04/13/2022, 2:24 PM
Is there a way to
cancelAllChildren
of a
runTest
scope? I have a test where I inject the test
coroutineContext
into a ViewModel and I want to cancel all running jobs inside the ViewModel when the test ends.
class MyViewModel(coroutineContext: CoroutineContext = Dispatchers.Default) : ViewModel() {
    
    private val coroutineScope = viewModelScope + coroutineContext

    init {
        coroutineScope.launch { myFlow.collect { /* do something with collected items */ } }
    }
}

class MyViewModelTest {

    @Test
    fun testInitMyViewModel() = runTest {
        MyViewModel(coroutineContext) // coroutineContext from test injected here
        // test hangs and times out eventually because myFlow collection is not canceled
    }
}
t

Trevor Stone

04/13/2022, 2:28 PM
val job = Job()
val coroutineContext: CoroutineContext = coroutineContext + job

job.cancel()
might work
l

Lukasz Kalnik

04/13/2022, 2:30 PM
Yup, works perfectly! Thanks for a quick and helpful answer.
If only it could be somehow automatized...
Doesn't
coroutineContext
already have a
Job
which I could reuse?
p

Paul Woitaschek

04/13/2022, 2:53 PM
You can call into the children
l

Lukasz Kalnik

04/13/2022, 2:58 PM
How?
p

Paul Woitaschek

04/13/2022, 3:00 PM
Sth like coroutineContext[Job].children().forEach it cancel
Coding on my phone ;-)
l

Lukasz Kalnik

04/13/2022, 3:04 PM
Thanks, that works!
The part I was missing was the
coroutineContext[Job]
key!
Thank you so much for your help ❤️
p

Paul Woitaschek

04/13/2022, 3:05 PM
🤗 welcome
l

Lukasz Kalnik

04/13/2022, 3:38 PM
You can even do
coroutineContext[Job]?.cancelChildren()