https://kotlinlang.org logo
#compose
Title
# compose
m

Mini

02/28/2021, 4:44 PM
I am trying to combine multiple flows in a viewmodel, including a snapshotFlow. This seems to work fine when i reference the state value in a composable, however when writing unit tests for the viewmodel, the combine does not seem to be triggered by changes to the state value. Is this because the state does not currently have an active observer in my unit test?
combine(snapshotFlow { myMutableStateMap.toMap() }, stateFlowA, stateFlowB)
a

Adam Powell

02/28/2021, 4:47 PM
Compose UI sets up a global snapshot write observer that periodically sends snapshot apply notifications. If you don't set up a ComposeView somewhere in your tests, this doesn't happen.
There are two ways to make sure snapshots get applied such that your snapshotFlow emits new values: 1. call
Snapshot.sendApplyNotifications()
- this will send apply notifications for any snapshot state changes that you've made without a specific snapshot scope. 2. make your relevant snapshot changes inside a
Snapshot.withMutableSnapshot {}
block - the snapshot will apply atomically and dispatch to apply observers at the end of the block.
❤️ 1
so either make calls that will result in
myMutableStateMap
changing inside a
Snapshot.withMutableSnapshot {}
block in your test code, or call
Snapshot.sendApplyNotifications()
after making those calls. Perform your assertions/await new flow values after whichever one you choose.
🙌 1
m

Mini

02/28/2021, 4:56 PM
Thank you Adam! I just tested both, and either seem to be working fine. I assume this means that I dont have to wrap the changes to
myMutableStateMap
with
withMutableSnapshot
in the viewmodel, is that correct? Is there any reason to prefer sendApplyNotifications or withMutableSnapshot in the tests, or is that completely up to my personal preference?
a

Adam Powell

02/28/2021, 5:09 PM
I've used both, it's mostly up to how you want it scoped. Don't wrap changes to
myMutableStateMap
with
withMutableSnapshot
in your actual app code unless you want to ensure that if you make several snapshot object changes that they're always seen by different threads as happening atomically. In tests it depends on when you want to publish visibility of changes between threads.
1
The snapshot system has been written such that if you don't know how it works, it mostly just silently meets your expectations of working like any other plain kotlin object/reference. You shouldn't have to write your code assuming any differently unless you want additional features out of snapshots at that point.
2 Views