This story describes how to implement Coroutines with Retrofit to fetch info from Webserver and also how to write unit test cases for Coroutines

The below ViewModel method uses Coroutine to fetch data from Server:

viewModelScope.launch: Coroutine is launched using this extension provided as part of Android KTX , which is licecycle aware as any coroutine launched in this scope is automatically canceled if the ViewModel is cleared.

The Dispatcher that is passed to this Coroutine specifies which Thread this Coroutine should run . This Dispatcher to be passed as argument to ViewModel as it will be helpful during UnitTesting to pass TestCoroutineDispatcher during unittesting .

@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun fetchResponseFromAPI(){
viewModelScope.launch (dispatcher){
// postsMutableLiveData.postValue(null)
try{

val response = apiService.fetchUserPosts()
if(response.isSuccessful){
postsMutableLiveData.postValue(response.body())
loading.postValue(false)
// loading.value = false
}else{
loading.postValue(false)
errorOnAPI.postValue("Something went wrong::${response.message()}")
}



}catch (e:Exception){
loading.postValue(false)
errorOnAPI.postValue("Something went wrong::${e.localizedMessage}")
}

}

}

Unit TestCases for Coroutine using Mockito:

val testDispatcher = TestCoroutineDispatcher()
@Test
fun `check viewmodel fetches data correctly`() = testDispatcher.runBlockingTest{
var retroRxModel = RetroRxModel("tile", "body", "1")
var retroRXModelList = ArrayList<RetroRxModel>()
retroRXModelList.add(retroRxModel)
response = Response.success(retroRXModelList)
retroCoroutineViewModel = RetroCoroutineViewModel(testDispatcher,apiService)
if (retrofit != null) {

if (apiService != null) {
Mockito.`when`(apiService.fetchUserPosts()).thenReturn(response)
}
}

retroCoroutineViewModel.fetchResponseFromAPI()
// advanceTimeBy(15_000)
println("Loading Val::::${retroCoroutineViewModel.fetchLoadStatus()?.value}")
println("PostLive Dat::::${retroCoroutineViewModel.fetchPostLiveData().value}")
Assert.assertEquals(1,retroCoroutineViewModel.fetchPostLiveData().value?.size)
Assert.assertEquals(false, retroCoroutineViewModel.loading?.value)



}

The testdispatcher to be passed as part of argument to ViewModel inorder to unit test ViewModel . This Dispatcher will have its own scope that does not wait when Coroutine executes on background thread to fetch results which is not needed during unit testing.

Please find below code Links for the same:

RetroCoroutineViewModel.kt

RetroCoroutineViewModelTest.kt

Source Code:

Kotlin Coroutine Dependencies:

def coroutine_version = "1.3.4"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutine_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutine_version"


//Coroutine Testing ......
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.4'
// Testing

testImplementation "org.mockito:mockito-core:3.3.3"
testImplementation 'androidx.arch.core:core-testing:2.1.0'

implementation "android.arch.lifecycle:extensions:1.1.1"
implementation "android.arch.lifecycle:viewmodel:1.1.1"

--

--