In my ViewModel there's a StateFlow
which seems to prevent my unit test from ever completing, i.e. the test "hangs". I'm fairly new to the Flow lib and not sure how to cancel/disable said StateFlow
so I can run my test as normal.
I created a simplified version of the code to highlight my problem. Here's the ViewModel in question:
@ExperimentalCoroutinesApi
class MyViewModel(
private val someApiClient: SomeApiClient,
private val dispatchers: CoroutineContexts = DefaultCoroutineContexts,
private val someLogger: SomeLogger
) : ViewModel() {
private val queries = MutableSharedFlow<String>()
@FlowPreview
val suggestions: StateFlow<Result<Throwable, String>> =
queries
.sample(THROTTLE_TIME)
.distinctUntilChanged()
.mapLatest {
try {
val downloadedSuggestions = someApiClient.getSuggestions(it)
Result.Success(downloadedSuggestions)
} catch (exception: Throwable) {
Result.Error(exception)
}
}
.flowOn(dispatchers.io)
.stateIn(viewModelScope, SharingStarted.Eagerly, Result.Success(""))
fun dispatchEvent(event: MyEvent) {
when (event) {
is SearchEvent -> someLogger.logStuff()
}
}
}
And the test looks like this:
@ExperimentalCoroutinesApi
class MyViewModelTest {
@get:Rule var mockitoRule: MockitoRule = MockitoJUnit.rule()
@get:Rule val coroutinesTestRule = MainDispatcherRule()
@Mock lateinit var someApiClient: SomeApiClient
@Mock lateinit var someLogger: SomeLogger
lateinit var myViewModel: MyViewModel
@Before
fun setUp() {
myViewModel = MyViewModel(
someApiClient,
coroutinesTestRule.testDispatcher.createCoroutineContexts(),
someLogger
)
}
@Test
fun `my test`() = runTest {
// When
myViewModel.dispatchEvent(SearchEvent)
// Then
verify(someLogger).logStuff()
}
}
I tried a suggestion from the Android Developer documentation page in the test:
@Test
fun `my test`() = runTest {
// Given
val dispatcher = UnconfinedTestDispatcher(testScheduler)
val job = launch(dispatcher) { myViewModel.suggestions.collect() }
// When
myViewModel.dispatchEvent(SearchEvent)
// Then
verify(someLogger).logStuff()
job.cancel()
}
But it didn't help. I feel like I'm missing something fairly obvious but can't quite put my finger on it. Any suggestions are welcome.