Mini
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).