How do you properly test an Http
request/response with Retrofit
and Coroutines
?
I'm using the latest Retrofit
version: 2.6.0
which has the support on the suspend
functions.
Edit
I'm also providing some code for easy implementation:
ApiInterface
@GET
suspend fun getCountriesListAsync(@Url url: String): Response<ArrayList<Country>>
Some Repository
suspend fun makeCountryApiCallAsync(): Response<ArrayList<Country>> =
treasureApi.getCountriesListAsync(COUNTRIES_API_URL)
Implementation on the ViewModel
:
private suspend fun makeCountriesApiCall() {
withContext(Dispatchers.Main) {
switchProgressBarOn()
}
try {
val countriesListResponse = setupRepository.makeCountryApiCallAsync()
if (countriesListResponse.isSuccessful) {
withContext(Dispatchers.Main) {
switchProgressOff()
countriesList.value = countriesListResponse.body()
}
} else {
withContext(Dispatchers.Main) {
showErrorLayout()
}
}
} catch (e: Exception) {
e.printStackTrace()
withContext(Dispatchers.Main) {
showErrorLayout()
}
}
}
I suppose you are asking how to test coroutines?
You should test wherever your logic is. As I see your Repository does not contain any logic beside Api call. If this is the case you can't test against live data because it's inconsistent but you can use WireMock or Mockito to mock some result and try to make it goes through your logics.
There's coroutine test support that you can have a look at it.
Here's an example
Essential for coroutine test (you can do without but with this is much easier)
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.0-M1'
Optional that I use to mock my call results
testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:2.1.0'
With what you gave as example
@ExperimentalCoroutinesApi
class ViewModelTest {
private val testDispatcher = TestCoroutineDispatcher()
private val testScope = TestCoroutineScope(testDispatcher)
@Before
fun before() {
Dispatchers.setMain(testDispatcher)
}
@After
fun after() {
Dispatchers.resetMain()
testScope.cleanupTestCoroutines()
}
@Test
fun testYourFunc() = testScope.runBlockingTest {
val mockRepo = mock<MyRepository> {
onBlocking { makeCountryApiCallAsync("") } doReturn Response.success(listOf())
}
val viewModel = TheViewModel(mockRepo)
val result = viewModel.makeCountriesApiCall() // Or however you can retrieve actual changes the repo made to viewmodel
// assert your case
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With