7

I am making some http requests in kotlin with fuel library. I want to test that code using mockk library. I figured out how to mock http requests. Below is the code for that.

    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())

I do not like that any() here. I want to be specific about the http method and the url. I would like to return specific responses based on the url being called and the http method being used.

I figured may be I could do following

    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

But I am getting following error.

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)

What am I missing here?

user3745870
  • 321
  • 1
  • 5
  • 13
  • 1
    I think this kinds of questions are more appropriate to ask to gitter chat or github issues, as they are pretty specific. Anyway this issue is not related to MockK itself, it is about building apropriate request, which may be super hard to achieve. Just debug "Request.equals" method and compare what is included there. Thanks – oleksiyp Nov 14 '18 at 17:25
  • 2
    This is a perfectly acceptable question for StackOverflow. – Louth Apr 02 '19 at 02:10

3 Answers3

1

To all those people that ended up here trying to find a solution to this, I've found something that solves the problem for my use case (but there are likely many use cases it's not appropriate for and I accept that it may not be the nicest...).

Provided you always have the calls to different endpoints in the same order every time you can do -

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

Which will return the next response body for every subsequent call to the Fuel client.

The full code would look like (using OP's example) -

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())

I suspect the correct way to do this is with a 'CustomMatcher' extension function on the MockKMatcherScope as detailed here. I could only get the mock to response with the last item that'd been mocked when doing that, rather than the correct item but YMMV...

Rich
  • 11
  • 2
0

Try to use following:

 every { client.executeRequest(req) } returns <mock object>
Vova
  • 956
  • 8
  • 22
0

You could try these lines. Regarding how to intercept fuel request.

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)
}

then, use it like this

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

BTW, this code not fully tested. Use at your own risk

nanangarsyad
  • 690
  • 14
  • 23