Mini
02/08/2022, 7:11 PMMini
02/08/2022, 7:11 PMclass MyTest() : FunSpec({
val dispatcher = TestCoroutineDispatcher()
listeners(MainCoroutineListener(dispatcher), MtLogListener())
class MyViewModel : ViewModel(){
val x = MutableStateFlow(5)
val y = MutableStateFlow(2)
val doubleX = x.map {
it * 2
}.stateIn(
viewModelScope,
SharingStarted.Eagerly,
null
)
val combinedFlow = x.combine(y){ xValue, yValue ->
xValue * yValue
}.stateIn(
viewModelScope,
SharingStarted.Eagerly,
null
)
}
val viewModel = MyViewModel()
test("stateflow mapped"){
viewModel.doubleX.value shouldBe 10
viewModel.x.value = 9
viewModel.doubleX.value shouldBe 18
}
test("combined"){
viewModel.x.value = 10
viewModel.y.value = 3
viewModel.combinedFlow.value shouldBe 30
}
}){
override fun isolationMode(): IsolationMode = IsolationMode.InstancePerLeaf
}Nick Allen
02/08/2022, 10:02 PMTestCoroutineDispatcher will immediately run top-level launched“ coroutines, but not nested coroutines (this is to avoid stack overflows). combine launches coroutines to collect from each Flow . map just calls the transform directly. Here the top-level coroutine is the stateIn coroutine collecting from the combine/map derived Flow . For map , that's all there is, no nested launching so it runs completely. For combine the nested coroutines to read from the combined `Flow`s are not run immediately.
If you tell the dispatcher to runCurrent before checking the value, then it'll work.
I'm assuming the Main dispatcher is setup correctly (it's not obvious to me from the snippet).