Stylianos Gakis
06/12/2023, 9:36 AMclass FakeFoo : Foo {
val responseTurbine = Turbine<Bar>()
override suspend fun invoke(): Bar {
return responseTurbine.awaitItem()
}
}
Then in a test, I am testing the result of a StateFlow, which comes from a result of combining two things, something like this
val data: StateFlow<State> = combine(someOtherFlow, flow { emit(FakeFoo().invoke()) }.onStart{ emit(null) }) { someOtherFlowValue, bar -> State(someOtherFlowValue, bar) }
But in one particular test I am not interested in the result of FakeFoo, so I want to rely on just the initial value emitted from the onStart
(Is a StateFlow with a default value in my case) to only test the other half of the combine
, whatever comes from someOtherFlow
. However, since this Turbine<Bar>
doesn’t ever get a value, but I am awaiting on it, it crashes my test with “no value received in X seconds”.
Doing cancelAndIgnoreRemainingEvents()
isn’t an option either, since now instead of infinitely waiting on awaitItem()
it will instead crash with “Expected item but found Error”.
Is there some other approach I can take instead? Maybe I shouldn’t be using a Turbine for my fake impl? I’ve taken inspiration to go with this approach from and it has worked flawlessly in all the other cases I’ve tried.Stylianos Gakis
06/12/2023, 9:40 AMcombine
call, in the test I now need to pass values to both, even though I only wanna test one of them in some of the tests which are meant to be simpler.Stylianos Gakis
06/12/2023, 9:45 AMprivate class FakeFoo(
block: Turbine<Bar>.() -> Unit = { add(SomeSaneDefault) },
) : Foo {
val responseTurbine = Turbine<Bar>().apply(block)
override suspend fun invoke(): Bar {
return responseTurbine.awaitItem()
}
}
So that from the test perspective, it can just be calling FakeFoo()
and at least visually it will not draw more attention than it needs to draw.
With the downside that someone could accidentally rely on this default behavior, and make that test much less intuitive to read and understand 😅Benoit Quenaudon
06/12/2023, 11:01 AMStylianos Gakis
06/12/2023, 11:03 AMnull
timeout is the default parameter though, and that seems to default to 3 seconds somehow. https://github.com/cashapp/turbine/blob/c7c3a68a32edfcd7c65102e630647b4808f8d058/src/commonMain/kotlin/app/cash/turbine/Turbine.kt#L98Benoit Quenaudon
06/12/2023, 11:03 AMtimeout If non-null, overrides the current Turbine timeout for this [Turbine]
Benoit Quenaudon
06/12/2023, 11:03 AMStylianos Gakis
06/12/2023, 11:06 AMI would just send a fake response you could ignore thenYeah I guess I gotta do that. Just makes the test bloated with unrelated stuff, which is what I wanted to avoid if at all possible.
baxter
06/15/2023, 5:25 AMtimeout
operator to the flow of something like a millisecond. It'll throw a cancellation exception on the upstream flow, but allows you to catch it downstream, so your coroutine isn't cancelled.Stylianos Gakis
06/15/2023, 6:45 AM