In tests, where multiple items are emitted by a fl...
# coroutines
f
In tests, where multiple items are emitted by a flow, the collector is missing some items because the emissions happen without a context switch., This may be easier to see with an example, see thread for details
this is a simplified version of what is under test. The real implementation needs a
flow
because there are 2 flows being `combine`d
Copy code
val query = MutableStateFlow("")
val sample: Flow<SomeObject> = query
    .debounce(400L)
    .distinctUntilChanged()
    .flatMapLatest {
        flow {
            emit(State.Loading)
            val response = interactor.getThing(params)
            if (response.isSuccess) {
                emit(state.Loaded(response.objects))
            } else {
                emit(state.Error(reason))
            }
        }
    }
the fake implementation uses a
Turbine
as shown here
Copy code
class FakeGetThingInteractor : GetThingInteractor {
    val things = Turbine<List<Thing>>()

    suspend fun getThings(params: Params): List<Thing> {
        return things.awaitItem()
    }
}
when I test this flow, you'd expect
Loading
and
Loaded
, but
Loading
is not received because it gets quickly replaced by
Loaded
. I have solved this by passing the
backgroundScope.coroutineContext
to the fake as shown here
Copy code
class FakeGetThingInteractor(
    private val context: CoroutineContext,
) : GetThingInteractor {
    val things = Turbine<List<Thing>>()

    suspend fun getThings(params: Params): List<Thing> = withContext(context) {
        things.awaitItem()
    }
}
which works, but I wonder if there is a simpler solution. I also tried a
yield
in the fake after the
awaitItem
call, but that didn't help
p
I assumed that because Turbine collects it in unconfined fashion it would not miss any emission Btw your flatMapLatest could be simplified to transformLatest
f
This is a simplified example, I'm trying to figure out a way to collect all items