https://kotlinlang.org logo
#coroutines
Title
# coroutines
k

Kshitij Patil

05/03/2021, 3:32 PM
How to test
MutableSharedFlow
with
replay=0
? I'm using turbine for testing Kotlin Flows and I managed to write tests for
MutableStateFlow
, but the same emitted values doesn't work for SharedFlows.
e

Erik

05/04/2021, 12:22 PM
Without replay, the shared flow won't emit to late collectors!
So first call
sharedFlow.test {
Then interleave assertions and emissions of values before
}
k

Kshitij Patil

05/04/2021, 12:27 PM
You mean emit values inside
test { }
block only?
e

Erik

05/04/2021, 12:37 PM
Well, that depends on what you want to test
If you want to test that emissions are dropped without subscribers, then emit outside of the test block
k

Kshitij Patil

05/04/2021, 1:29 PM
I believe with the introduction of
SharedFlow
and
StateFlow
, Channels are considered to be low level APIs. So, I'm trying to use
MutableSharedFlow
to build a mock class wrapping some state and I use public methods of this clas to mutate that state, thus, transformed objects are emitted to a private
MutabelSharedFlow
and a Public Flow is where I'm expecting those changes to appear. So I was calling that public method in
@Before
section and was expecting those events to appear in
SharedFlow
unit test. Will try your suggested approach and let you know how it goes. Thanks!
e

Erik

05/04/2021, 2:18 PM
Channels are fine to be used! They still have use cases. There are specific channel implementations that are now obsolete since shared and state flows exist
u

ursus

05/04/2021, 5:30 PM
yes .test first
k

Kshitij Patil

05/05/2021, 6:02 AM
@Erik can you point to some talk/article explaining use cases of SharedFlow/StateFlow vs the Channels and Actors
e

Erik

05/05/2021, 6:05 AM
A few examples: https://elizarov.medium.com/shared-flows-broadcast-channels-899b675e805c If course, not all use cases can be described in one place, but in general these examples apply to many cases
k

Kshitij Patil

05/05/2021, 7:15 AM
It works this way. Am I doing it right?
e

Erik

05/05/2021, 8:06 AM
No need to
launch
You can
Copy code
flow.test {
    // assert initial behaviour, e.g. emission(s) or error

    // call stuff that should make the flow do something
    // assert that the flow does it

    // repeat previous steps as often as you like

    // assert final state, e.g. flow completed or flow does nothing more
}
k

Kshitij Patil

05/05/2021, 8:41 AM
Could be done, thought doing it this way might mimic operating in different coroutines as everything inside
test { }
is run within same Job and we should mainly be doing collect operations there.
e

Erik

05/05/2021, 10:33 AM
The benefit is that you assert the actions and flow's events in the order that they happen
If you do all actions and just assert the correct events afterwards, you aren't sure about what events happened on what actions. That might be good enough, but in some cases actual behaviour testing can be preferable
👍 1
In the latter case you don't need Turbine, though. You could just collect the flow as a list (if it completes, shared flows never complete. If a shared flow, you could e.g.
take
values), and assert that the list is as expected.
k

Kshitij Patil

05/05/2021, 3:57 PM
Yes I agree. I was just trying to create simplistic example to ask the question and I do got the clarification about
SharedFlow
I needed. Will be useful in some complex scenarios I have in the codebase.
85 Views