如何在Kotlin中用模拟和燃料模拟POST请求?

时间:2018-11-13 12:24:02

标签: http kotlin request mockk

我正在用燃料库在Kotlin中发出一些http请求。我想使用模拟库测试该代码。我想出了如何模拟http请求。下面是该代码。

    val client = mockk<Client>()
    every { client.executeRequest(any()).statusCode } returns 200
    every { client.executeRequest(any()).responseMessage } returns "test"
    every { client.executeRequest(any()).data } returns "abc".toByteArray()

    FuelManager.instance.client = client

    assertEquals("abc" , testHttpRequest())

我不喜欢这里的any()。我想具体介绍http方法和url。我想基于被调用的url和所使用的http方法返回特定的响应。

我认为我可以做到

    val req = Request(Method.POST, "my/test", URL("https://testRequest.com"), timeoutInMillisecond = 3000, timeoutReadInMillisecond = 3000)

    every { client.executeRequest(req).statusCode } returns 200
    every { client.executeRequest(req).responseMessage } returns "OK"
    every { client.executeRequest(req).data } returns "abc".toByteArray()

    FuelManager.instance.client = client

但是我遇到以下错误。

io.mockk.MockKException: no answer found for: Client(#1).executeRequest(--> 
https://testRequest.com/my/test
"Body : abc"
"Headers : (3)"
Accept-Encoding : compress;q=0.5, gzip;q=1.0
Content-Type : application/json
Authorization : Basic xxx)

我在这里想念什么?

3 个答案:

答案 0 :(得分:1)

对于所有最终在此寻求解决方案的人,我发现了可以解决我的用例问题的东西(但是可能有很多用例都不适合我,我接受它可能不是最好的...)。

只要您每次都能始终以相同的顺序呼叫不同端点-

every { client.executeRequest(any()).data} returnsMany listOf(responseBody1, responseBody2, ... , responseBodyN)

对于随后的每个对Fuel客户端的调用,哪个都会返回下一个响应正文。

完整的代码看起来像(使用OP的示例)-

val response1 = "This is response one"
val response2 = "This is response two"

val client = mockk<Client>()
    every { client.executeRequest(any()).statusCode } returns 200
    every { client.executeRequest(any()).responseMessage } returns "test"
    every { client.executeRequest(any()).data } returnsMany listOf(response1.toByteArray(), response2.toByteArray())

    FuelManager.instance.client = client

    assertEquals("This is response one", testHttpRequest())
    assertEquals("This is response two", testHttpRequest())

我怀疑正确的方法是使用MockKMatcherScope上的'CustomMatcher'扩展功能,详细说明here。我只能让模拟对象对执行此操作时最后被模拟的项目做出回应,而不是正确的项目,而是YMMV ...

答案 1 :(得分:0)

尝试使用以下内容:

 every { client.executeRequest(req) } returns <mock object>

答案 2 :(得分:0)

您可以尝试以下行。关于如何拦截加油请求。

fun interceptFuel(method: Method, url: String) {
    val interceptor = { next: (Request) -> Request ->
        { req: Request ->
            if (req.method == method && req.url.toString() == url) {
                val client = mockk<Client>()
                /*mock fuel into whatever you like*/
                FuelManager.instance.client = client
            }
            next(req)
        }
    }
    FuelManager.instance.addRequestInterceptor(interceptor)
}

然后,像这样使用它

interceptFuel(Method.GET, "https://google.com") 

顺便说一句,此代码尚未完全测试。使用后果自负