https://kotlinlang.org logo
Title
t

Thomas Flad

12/09/2021, 12:42 PM
Hi everyone 👋🏼 I want to use a SharedFlow created with the
shareIn
operator +
WhileSubscribed
to cancel/resume the SharedFlow in
repeatOnLifecycle
when the Android App goes to background. It’s working fine so far. I also combine this flow with a MutableStateFlow in my ViewModel to react on user input and update my state.
class MyViewModel(
    dataSource: MyDataSource,
    sharingStarted: SharingStarted = WhileSubscribed(5000)
) : ViewModel() {

    var userInput = MutableStateFlow(1)

    val state = dataSource.dataFlow()
        .combine(userInput) { data, userInput ->
            OutputClass(data, userInput)
        }
        .shareIn(viewModelScope, sharingStarted, 1)

}
My issue is that I want to test this. I’ve tried to use Turbine for this but it does not help with the combine.
@Test
fun testMyViewModel() = runBlockingTest {

    val cut = MyViewModel(
        mockk { coEvery { dataFlow() } returns flowOf(Data()) },
        sharingStarted = SharingStarted.Eagerly
    )

    cut.state.test {

        // Also an emit to the userInput here does not help
        // cut.userInput.emit(2)
        
        assertEquals(OutputClass(...), awaitItem())
    }


}
I’m getting a timeout instead of the result.
t

Tgo1014

12/09/2021, 12:48 PM
I guess there’s some weird stuff when using Turbine with
runBlockingTest
👆 1
u

ursus

12/09/2021, 12:54 PM
state vs taskListState is a typo?
t

Thomas Flad

12/09/2021, 12:55 PM
@ursus Sorry, yes it’s a typo
u

ursus

12/09/2021, 12:57 PM
first try runBlocking instead of runBlockingTest, second try adding doOnNext on .state flow to see if it even emits at all + printlns inside my code.. thats how I deal with this
also try adding userinput via the .value setter, not emit(), but yea im aware you have the default and its not necessary
t

Thomas Flad

12/09/2021, 3:02 PM
Thanks for helping out! Using
runBlocking
didn’t help. What solves the issue kind of is when I pass a scope to the ViewModel and use the TestCoroutineScope for the
shareIn
instead. But then I’ll get
Test finished with active jobs
u

ursus

12/09/2021, 3:07 PM
Thats odd, all turbine does is suspend on awaitItem until the flow emits, so it shouldnt matter what scopes bla bla. If you remove the
shareIn
sharing, does it work?
t

Thomas Flad

12/09/2021, 3:16 PM
Without the shareIn the tests are working fine (with Turbine). What I don’t understand is that the test is working when I don’t combine with the MutableStateFlow. I can test the
shareIn
without the combine
e

expensivebelly

12/09/2021, 4:56 PM
So it’s either testing
combine
or
shareIn
but not both?
n

Nick Allen

12/09/2021, 5:57 PM
Never used Turbine but docs suggest to me that you are missing
cancelAndConsumeRemainingEvents()
at end of
test
block.
test
doesn't return until
Flow
is complete or cancelled. The result of
shareIn
never completes so you need to cancel it. https://github.com/cashapp/turbine#hot-flows