Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)
like image 757
John O'Reilly Avatar asked Oct 07 '18 20:10

John O'Reilly


2 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

like image 96
qwwdfsad Avatar answered Oct 12 '22 07:10

qwwdfsad


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!

like image 44
John O'Reilly Avatar answered Oct 12 '22 07:10

John O'Reilly