I want to test if a certain event was emitted to m...
# coroutines
v
I want to test if a certain event was emitted to my shared flow, but that event gets emitted in the init function before I can observe the flow in my test. How do I test that this event was actually emitted?
Copy code
@Test
    fun `test event is emitted`() = coroutineRule.runBlockingTest {

       val viewModel = MyViewModel()
       launch {
            val elements = viewModel.mySharedFlow.take(1).toList()
            elements[0] shouldBeEqualTo MyEvent
        }
    }
// ViewModel
Copy code
val mySharedFlow = MutableSharedFlow<MyEvent>(extraBufferCapacity = 1)

 init {
    mySharedFlow.tryEmit(MyEvent)
 }
z
As a general rule, it’s usually better to avoid side effects in constructors. This is one reason why. If you make an explicit
start()
method, you can decide when to call it in your test.
d
As a cheeky workaround though....... replay cache?
v
I’ll try replaying cache. Thanks
z
If this flow is actually used for events and not state, as the name suggests, you probably don’t want to replay them to new subscribers? This is also a problem you’ll have in non-test code though – no external code will have had the opportunity to interact with your instance at all, let alone start collecting a flow, before the constructor returns.
☝️ 1
v
That makes sense, I’ll restructure the code. Thank you both
m
Here’s how I handle my events (if you want a different take): https://proandroiddev.com/android-singleliveevent-redux-with-kotlin-flow-b755c70bb055 TL;DR I use a channel (receiving it as a flow) so events are buffered until an observer can observe them. I have no issues emitting values in the constructor.