Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock a POST request with mockk and fuel in kotlin?

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?

like image 276
user3745870 Avatar asked Nov 13 '18 12:11

user3745870


People also ask

How do you verify in MockK?

verify supports the same argument matchers as every , along with a few additional matchers. Inside the verification block (between the opening curly bracket { and closing curly bracket } ), you write the method you want to verify.

What is MockK relaxed?

A relaxed mock is the mock that returns some simple value for all functions. This allows you to skip specifying behavior for each case, while still stubbing things you need.

What is mockkStatic?

Mocking static methods Again, MockK provides specialized functions to mock static methods. mockkStatic("com.name.app.Writer") Rather than passing a reference to the class, you pass the class name as a string. You can also choose to pass in a reference to the class, and MockK will figure out the class name.


1 Answers

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...

like image 112
Rich Avatar answered Oct 04 '22 02:10

Rich