Hello, can anyone help me understand why I must s...
# coroutines
s
Hello, can anyone help me understand why I must start collecting a state flow in order for
runTest
to be finished (all child coroutines finished)? I can't seem to be able to wrap my head around why using
SharedStarted.Eagerly
or collecting the value inside
runTest
directly has any effect on that while
Lazily
does not.
Copy code
class PreferencesActionRepository @Inject constructor(
    private val scopedPreferencesService: ScopedPreferencesService,
    scope: CoroutineScope,
) : ActionRepository {

    // map to a stateflow so that the parsed object can be cached
    override val actions =
        scopedPreferencesService.watchUserRoleActions()
            .map { userRolesToActionsJson ->
                userRolesToActionsJson.takeIf {
                    it.isNotBlank()
                }?.let { json ->
                    roleActionsMapFromJson(json)
                }
            }
            .stateIn(
                scope = scope,
                started = SharingStarted.Lazily, // test succeeds with Eagerly
                initialValue = hashMapOf()
            )
}

// TEST, timeouts with an exception

@Test
fun `foo test`() = runTest {
    val preferenceMock = mock<ScopedPreferencesService>()
    val repository = PreferencesActionRepository(
            scopedPreferencesService = preferenceMock,
            scope = this
    )
}
j
If you use
Lazily
and you don't collect it at all, then no coroutine is started at all. If you use
Eagerly
, a coroutine is immediately started to collect and share the upstream flow. If you collect the state flow, even with
Lazily
, coroutine is started to collect and send values to your collector.
You should probably use the
backgroundScope
for this instead of
this
(
TestScope
) in your test
1
s
Ok, thank you for the explanation. I somehow managed to miss the hint in the exception raised that
backgroundScope
should be used.