是否可以在Kotlin中模拟改造的Deferred <Response <T >>?

时间:2019-06-12 11:44:37

标签: kotlin retrofit

我想知道我是否可以做这个模拟

Deferred<Response<Void>>

我是Kotlin的新手,而且是模拟的,但我没有成功。

到目前为止,我已经做到了:

我有一个客户端界面:

class MyClient {

@POST("/names")
    @FormUrlEncoded
    fun names(
        @Field("username") username: String
    ): Deferred<Response<Void>>

}

在我的测试中:

lateinit var myClient:MyClient

@Before
fun setUp() {
    client = mockk<MyClient>(relaxed = true)
    val response = mockk<Response<Void>>(relaxed = true)
    every { myClient.names(username) }.returns(mockedResponse)

}

我发现了很多有关Response的帖子(例如Handle empty response with retrofit and rxjava 2.x),但不确定如何处理“推迟”

或一些有关延期的问题(无法实现此答案。async在我的项目中无法解决

When using kotlin coroutines, how do I unit test a function that calls a suspend function?

这可能吗?我想念什么?

我正在测试的服务:

class MyService {

    fun doSomething(username: String) {
       myClient().names(username).await()
    }
}

2 个答案:

答案 0 :(得分:2)

您正在尝试返回一个Response<Void>的地方,而该地方需要Deferred<Response<Void>>

基本上,延迟的原因是可能尚未完成的作业的结果。推迟isCompleted后,结果就准备好了。在您的情况下,您很可能希望已将Deferred与响应一起完成。

要创建已完成且具有某些值的Deferred,可以使用CompletableDeferred(value: T)函数。

这是一个完整的示例,说明了如何从客户端模拟中返回完成的延迟操作。

interface GithubClient {
    @GET("users/{username}/repos")
    fun listRepos(@Path("username") username: String): Deferred<Response<Void>>
}

class RepoService(val client: GithubClient) {
    suspend fun doSomething(username: String): Response<Void> {
        return client.listRepos(username).await()
    }
}

class GithubClientTests {

    private lateinit var client: GithubClient

    @BeforeTest
    fun setUp() {
        // setup the mocked client
        client = mockk<GithubClient>(relaxed = true)
        val mockResponse = mockk<Response<Void>>(relaxed = true)
        every { client.listRepos(any()) } returns CompletableDeferred(mockResponse)
    }

    @Test
    fun testMockClient() = runBlocking<Unit> {
        // create the service with the mocked client
        val service = RepoService(client)
        val response = service.doSomething("octocat")

        // response is not successful, because we didn't specify any behavior for the mocked response
        assertFalse { response.isSuccessful }
    }
}

答案 1 :(得分:1)

我会说你错过了一个等待:

@Before
fun setUp() {
    client = mockk<MyClient>(relaxed = true)
    val response = mockk<Response<Void>>(relaxed = true)
    every { myClient.names(username).await() /* this would return an response instead of deferred */ }.returns(mockedResponse)
}

让我知道这是否有帮助!