In the Live Q&A chat Christina and I hosted a few weeks ago on GrokSwift.com, Steve asked about the best way to unit test REST API calls. Here’s his question:
Can you talk about the right way to unit test rest calls? What are the best tools for just testing endpoints?
I love this question — probably because I love unit tests. Here’s the first part of my response:
I generally test REST calls in multiple parts. First, I test that my Router class can properly create the endpoint URL as well as the parameters that go with it. (If you’re not familiar with a Router, check out the Alamofire docs for an example.)
But even if you’re not using Alamofire, you can still create a Router class that returns the proper HTTP method, path, and parameters for a given route. Say, for example, that you’re requesting data from the GitHub API. You might have a GitHubRouter with a route for SearchRepositories that gives you the method, path, and parameters you need to make a request, and you can easily verify those in your unit tests.
Here’s the second half of my answer:
Second, I test that my code can parse the JSON I get from my endpoint. So I like to use an app like Paw to grab the JSON from my endpoint, save it as a file in my test bundle, then feed that data into my parser in the tests. This makes the tests run much faster than going against a live API where you’d have to wait for a response, and much more stable (they don’t depend on the API to be up).
Let me repeat that last part: this makes the tests much more stable since they don’t depend on the API to be up. When you’re writing unit tests, you don’t want to risk test failures due to the API being down. You want your tests to fail if and only if your code is broken. If you’re testing with a live API, you have no way of knowing whether it’s your code or the server code that’s broken — or if the back-end team just decided to restart the server, redeploy the app, or bring the environment down for a while. It’s important that your unit tests only fail when your code breaks, so be sure to write unit tests for your JSON code. If you’re not sure where to start, you can get Parsing JSON in Swift which will walk you through the exact steps you need to fetch your JSON data, add it to your test target, write your tests, and implement your parser.
But what if you want to know your code works with the server? You can certainly write useful tests that depend on the server, but be sure to call them what they are — integration tests — and have the right expectations. The back-end will go down for a variety of reasons (especially if you’re testing against a dev or staging environment), so when integration tests fail, that should send a very different message from when unit tests fail. In your Xcode project, keep unit tests and integration tests in separate targets so you can easily tell which set failed and handle it appropriately. Just remember that integration tests aren’t a replacement for unit tests, but they can be a nice supplement.