Reputation: 321
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?
Upvotes: 7
Views: 5869
Reputation: 11
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...
Upvotes: 1
Reputation: 700
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
Upvotes: 0
Reputation: 1091
Try to use following:
every { client.executeRequest(req) } returns <mock object>
Upvotes: 0