Home » Android » android – Mocking return value of method that returns Kotlin Coroutines Deferred type

android – Mocking return value of method that returns Kotlin Coroutines Deferred type

Posted by: admin June 15, 2020 Leave a comment

Questions:

I’m using Kotlin Coroutines and in particular using Retrofit’s CoroutineCallAdapterFactory. I’m trying then to unit test a class that in turn utilizes Retrofit interface (GalwayBusService below).

interface GalwayBusService {

    @GET("/routes/{route_id}.json")
    fun getStops(@Path("route_id") routeId: String) : Deferred<GetStopsResponse>

}

In my unit test I have

val galwayBusService = mock()

and then trying something like following to mock what gets returned when that method is called. The issue is though that getStops returns a Deferred value. Is there any particular approach recommend for mocking APIs like this?

`when`(galwayBusService.getBusStops()).thenReturn(busStopsResponse)
How to&Answers:

The proper solution is to use CompletableDeferred.
It is better than writing async because it doesn’t launch anything concurrently (otherwise your test timings may become unstable) and gives you more control over what happens in what order.

For example, you can write it as whenever(galwayBusService. getBusStops()).thenReturn(CompletableDeferred(busStopsResponse)) if you want to unconditionally return completed deferred or

val deferred = CompletableDeferred<GetStopsResponse>()
whenever(galwayBusService.getBusStops()).thenReturn(deferred)
// Here you can complete deferred whenever you want

if you want to complete it later

Answer:

So, turns out the way to do this is to use async as below:

whenever(galwayBusService. getBusStops()).thenReturn(async { busStopsResponse })

Credit btw to https://twitter.com/_rafaeltoledo for the answer!