I want to test the following very common usecase as an Instrumented Test in Android:
- When clicking a button a fetch() function is called in my ViewModel
- This function tells the view to show a loading-overlay
- It executes a fetch in a coroutine
- After the result is fetched it lets the view know to display the result
Here is the function in my Viewmodel:
fun fetch() {
_loading.value = true //loading is shown
viewModelScope.launch {
val results = fetchUseCase() //suspend function
_result.postValue(results)
_loading.postValue(false) //loading is not displayed
}
}
Here is the test which works according to this CodeLab https://developer.android.com/codelabs/advanced-android-kotlin-training-testing-survey#4:
@HiltAndroidTest
@UninstallModules(CoroutinesDispatcherModule::class)
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTestJunit4Deprecated {
@get:Rule
var hiltRule = HiltAndroidRule(this)
@ExperimentalCoroutinesApi
@get:Rule
var mainCoroutineRule = MainCoroutineRule()
@Before
fun setup() {
ActivityScenario.launch(HomeScreenActivity::class.java)
}
@ExperimentalCoroutinesApi
@Test
fun fetchTest() {
//pausing the long running tasks
mainCoroutineRule.pauseDispatcher()
//When clicking the button
onView(withId(R.id.load_measurement_button)).perform(click())
//loading is shown
onView(withId(R.id.loading_overlay))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
//continue fetch
mainCoroutineRule.resumeDispatcher()
// loading is not shown anymore and the result is there
onView(withId(R.id.loading_overlay))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
onView(withId(R.id.message))
.check(matches(withText("0")))
}
}
Unfortunately "pauseDispatcher()" and "resumeDispatcher" are Deprecated. I tried to use the "StandardTestDispatcher" and "advanceUntilIdle()" but it does not work as expected. The coroutine is never resumed. How can this test be rewritten, such that it works:
- Without deprecated function calls
- Without changing the productive code ?