Hi, im currently learning to test StateFlow and an...
# coroutines
a
Hi, im currently learning to test StateFlow and and got into a problem where only the initialValue is emitted. The StateFlow is produced from combining multiple snapshotFlow and use stateIn. I have manually collected the Flow and set the dispatcher to Unconfined but still no luck. Anyone has any idea on what am i missing?
The code:
Copy code
@Test
fun testStateFlow2() = runTest {
    var emailState by mutableStateOf("")
    var passwordState by mutableStateOf("")

    val allInputValid: StateFlow<Boolean> = combine(
        snapshotFlow { emailState },
        snapshotFlow { passwordState }
    ) { emailValue, passwordValue ->
        emailValue.isNotEmpty() && passwordValue.isNotEmpty()
    }.stateIn(
        CoroutineScope(UnconfinedTestDispatcher(testScheduler)),
        SharingStarted.WhileSubscribed(5000),
        false
    )

    val test = mutableListOf<String>()
    val job = launch {
        allInputValid.collect {
            test.add("Value emitted: $it")
            println(it)
        }
    }

    advanceUntilIdle()
    emailState = "test_email"
    passwordState = "test_password"

    advanceUntilIdle()
    println(test)

    job.cancel()
}
r
StateFlow conflates values so maybe it's because the value hasn't changed?
Put a
println
inside
combine
lambda to see if it is getting invoked with new values and what it is emitting.
a
yes it only invoked once with empty value
email:  - pass: // inside combine
false // inside collect
[Value emitted: false] // last println before cancel
so the emailState and passwordState update value doesnt do anything, why that happens?
r
never mind. I didn't read that correctly.
I think it's because the test method is not a composable.
a
so snapshotFlow can only be triggered from composable only?
r
From the example here they're observing the
State<T>
from an observable. I don't think snapshotFlow is going to work unless
State<T>
is in a composable. But I'm am not an expert. https://developer.android.com/develop/ui/compose/side-effects#snapshotFlow
👏 1
a
It makes sense, thanks. I'll try to search/ask in the compose channel
Ah you are right, it needs a compose observer, now im confused why it is work on standard flow. Will try to ask in compose channel https://kotlinlang.slack.com/archives/CJLTWPH7S/p1614530850199700?thread_ts=1614530680.199100&amp;cid=CJLTWPH7S
z
Yea you need to bootstrap snapshot observation. Here’s how molecule does it (look for registerGlobalWriteObserver in that file, GitHub app apparently can’t link to lines), you can do something similar (probably don’t even need to launch just for your test)
👏 1
a
Thanks for the reference, TIL we can register our own observer for snapshot