Search code examples
androidkotlinmockitoretrofitkotlinx.coroutines

Mocking return value of method that returns Kotlin Coroutines Deferred type


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)

Solution

  • 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