模拟返回 Kotlin Coroutines Deferred 类型的方法的返回值

Posted

技术标签:

【中文标题】模拟返回 Kotlin Coroutines Deferred 类型的方法的返回值【英文标题】:Mocking return value of method that returns Kotlin Coroutines Deferred type 【发布时间】:2019-03-12 13:29:42 【问题描述】:

我正在使用 Kotlin 协程,特别是使用 Retrofit 的 CoroutineCallAdapterFactory。然后我正在尝试对一个类进行单元测试,该类又使用 Retrofit 接口(下面的GalwayBusService)。

interface GalwayBusService 

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


在我的单元测试中我有

val galwayBusService = mock()

然后尝试类似以下的方法来模拟调用该方法时返回的内容。问题在于 getStops 返回一个 Deferred 值。有什么特别的方法可以用来模拟这样的 API 吗?

`when`(galwayBusService.getBusStops()).thenReturn(busStopsResponse)

【问题讨论】:

【参考方案1】:

正确的解决方案是使用CompletableDeferred。 这比写async 更好,因为它不会同时启动任何东西(否则您的测试时间可能会变得不稳定),并且可以让您更好地控制以什么顺序发生的事情。

例如,如果要无条件返回已完成的deferred,可以写成whenever(galwayBusService. getBusStops()).thenReturn(CompletableDeferred(busStopsResponse)) 或者

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

如果你想稍后完成它

【讨论】:

【参考方案2】:

所以,原来的方法是使用async,如下所示:

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

将答案归功于https://twitter.com/_rafaeltoledo!

【讨论】:

以上是关于模拟返回 Kotlin Coroutines Deferred 类型的方法的返回值的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin Coroutines 协程实现原理全解析

Kotlin Coroutines不复杂, 我来帮你理一理

Kotlin Coroutines 中的 main-safe 是啥?

Kotlin Coroutines 的现有 3 函数回调

Kotlin Coroutines:等待多个线程完成

Kotlin Coroutines viewModelScope 中的改造调用