I have been trying for 2 days now to mock/stub Fuel, with no real luck.
I'm building a small piece of software which needs to perform a REST GET request to acquire some data. I'm using Fuel to request the data, which works fine, but I also want to be able to unittest my code.
I can see from the documentation that Fuel has a "test-mode", which makes it run in blocking mode, but I can't seem to figure out a way to stub out Fuel, such that it doesn't actually call the web-endpoint.
How do you stop Fuel from performing real web requests, during tests?
I have been trying to use mockito to mock out the fuel responses, but it gets very cumbersome very quickly, and due to all sorts of things being internal, sealed and static I'm having no luck.
Disclaimer: I'm new to Kotlin, so I might just have missed something blatantly obvious.
I also tried to create my own client and setting it on the FuelManager like this:
val someJson = "{\"key\":\"value\"}"
val client = object: Client {
override fun executeRequest(request: Request): Response {
val resp = Response()
resp.apply {
dataStream = someJson.byteInputStream()
}
return resp
}
}
FuelManager.instance.client = client
But when I try to set the dataStream I'm told by the compiler: Cannot Access 'dataStream': it is internal in 'Response'
Hmm, it seems that the ability to replace the client, broke with #172.
I have downgraded to version 1.7.0, where the following code works fine:
val someJson = "{\"key\":\"value\"}"
val client = object: Client {
override fun executeRequest(request: Request): Response {
return Response().apply {
data = someJson.toByteArray()
httpStatusCode = 200
httpResponseMessage = "OK"
}
}
}
FuelManager.instance.client = client
Yes. @FrederikNS I designed Client to be pluggable and the way you have done for mocking the response was correct. However, I agree with you that it becomes annoying after data has been set to internal.
I will open a PR to patch that in the next version. Or if you want to open a PR for that, I am more than happy to merge yours too!
Thanks for using Fuel and also reporting back the problem you may find. It meant a lot for me to improve this library further.
@FrederikNS I think this should be fixed with the new version. I will close this issue for now. If you don't think it satisfies you, feel free to reopen it again :)
I always wrap the network library I use so I can replace the library later or test it easily.
@FrederikNS check this snippet on how to rewrite it to mockk mocking library.
May be it's pretty similar to your code and do not add a lot of value here, but I believe in more sophisticated cases it can be useful.
val client = mockk<Client>()
val someJson = "{\"key\":\"value\"}"
every { client.executeRequest(any()).statusCode } returns 200
every { client.executeRequest(any()).responseMessage } returns "OK"
every { client.executeRequest(any()).data } returns someJson.toByteArray()
FuelManager.instance.client = client
@oleksiyp Genius! Thanks!
val someJson = "{\"key\":\"value\"}"
val client = mock<Client> {
onGeneric { executeRequest(any()) } doReturn Response(
statusCode = 200,
responseMessage = "ok",
dataStream = ByteArrayInputStream(someJson.toByteArray()),
url = URL("https://www.mydomain.test")
)
}
FuelManager.instance.client = client
Most helpful comment
@FrederikNS check this snippet on how to rewrite it to mockk mocking library.
May be it's pretty similar to your code and do not add a lot of value here, but I believe in more sophisticated cases it can be useful.