Reputation: 2213
I have a function which makes an API call to a an external API
Let us say the function does something simple like the below. FYI need to import scala.io.Source
def myFunction(apiRequestUrl: String) : MyObject = {
val response: String = Source.fromURL(apiRequestUrl).mkString
val formatedResponse: MyObject = formatResponseFunction(response)
formatedResponse
}
I know that some error codes I could receive are 400, 404, etc... and I'd like to just handle any error code generically from this. How could this be done? The examples I've found seem to be testing a person's own built REST API, and not function calls to someone else's external API
Upvotes: 1
Views: 3130
Reputation: 1497
First of all, you have to inject the dependencies you want to replace with mocks, static calls within a function can't be mocked/stubbed.
In your Scenario you have another problem: your dependency Source
is an object, and you can't mock objects, only non-final classes and traits. Furthermore, it is considered a bad practice to mock 3rd party APIs.
A good way to solve all those problems would be to re-write the code like
trait HttpAdapter {
def fromUrl(apiRequestUrl: String): String = Source.fromURL(apiRequestUrl).mkString
}
object HttpAdapter extends HttpAdapter
def myFunction(apiRequestUrl: String, httpAdapter: HttpAdapter = HttpAdapter) : MyObject = {
val response: String = httpAdapter.fromUrl(apiRequestUrl)
val formatedResponse: MyObject = formatResponseFunction(response)
formatedResponse
}
"myFunction" should "work" in {
//create mock
val http = mock[HttpAdapter]
//stub mock
http.fromUrl("some url") shouldReturn "result"
//inject mock
myFunction("some url", http) shouldBe MyObject
}
Notice I've wrapped the third party API in a class I have full control over (HttpAdapter
) and then I mock that one
Then I inject httpAdapter
as a parameter, but I provide a default value so the callers do not need to worry about it, while I can still override it with a mock or stub in test code.
Also note that I've used mockito-scala instead of regular mockito, so the stubbing syntax is different.
Upvotes: 1
Reputation: 3638
For mocking the external service calls, you could use Mockito which is a mocking framework. Mockito is very simple to use and you can provide stubs for your external calls. For example
val m = mock[io.Source.type]
Here you mock the Source and then you provide your desired behaviour on invocation of the fromUrl
function.
i.e
when(m.fromUrl("external service url")) thenReturn("result")
Upvotes: 2