Effective web API testing on iOS
Many iOS apps contain code which relies on a third-party web service for data or another type of behavior. Testing this interface is often ad-hoc at best. Any errors encountered are swallowed into the abyss of ‘that only happens with bad connectivity …’ Development which relies on the availability of an interface can also be problematic; such as requiring VPN access to hit a not-yet released server, or other factors. This article contains a sample walk-through of testing an imaginary web service with ILTesting, AFNetworking and Kiwi. It’s assumed the reader is familiar with the basics of Cocoa Touch, XCode and project creation.
If you’re a solid iOS dev but not familiar with Kiwi or AFnetworking, please check them out:
It should be noted the approach shown using ILTesting will work with most any testing framework or networking library on iOS.
Example DogPark Application
The example application repo is located here on Github: DogPark
In our example application, we’ll be testing an implementation of an imaginary Dog Park API client. The client sends requests over HTTP and presently has two methods:
We’ll get to the fun of testing a Dog Park API soon, but first a little about the network testing library we’ll be using.
Intro To ILTesting (GitHub)
The magic behind ILTesting is simple: it ingeniously registers itself as an NSURLPrototcol handler thereby getting “first dibs” to handle HTTP requests from the application. (A more technically in-depth article on NSURLProtocol is available here : NSHipster .)
The registration of a pre-defined HTTP handler effectively keeps our app from hitting the network. (This speeds up our tests!) But the main point is predictively crafting an HTTP response for a given URL.
(If you’re wondering ‘why not just mock AFNetworking instead’, I shy away from mocking code that I did not write myself.)
Let’s take a look at a couple ILTesting class methods:
The ILTesting Delegate
ILTesting allows for delegation of client response data to a class which implements the protocol.
The protocol-delegate protocol looks like this and includes several optional methods:
Within the sample application, the delegate is implemented in HKZFakeWebsServer.
A tip for dealing with large APIs is to have several different classes each implement CannedURLProtocol and break up response testing between various functional areas. Ex - billing, user authentication, etc.
Enough stuffy code talk, let’s get going and have some fun!
Back to the DogPark
So anyway, we need to test our example APIClient methods. When beginning network testing, this process has proved successful:
Capture the desired JSON response from the API and save it within a file. (In the sample application, these are kept within the DogParkTests/JSON folder.
Create a trigger within the ILTesting delegate to serve the response.
Write a test which utilizes the response.
Take a look at HKZFakeWebserver which implements ‘responseDataForClient’ which is self explanitory ;) - it loads various JSON files as response data when specific URLs are requested. The request is matched on HTTP verb and path.
Taking things further - Completing the implementation
Within the sample application, both tests presently fail. I leave the implementation of the client to the reader as an exercise in using ILTesting. The example code also serves as a reference to employ this testing method in your own project.
1) Original idea of injecting test data via NSURLProtocol goes to Claus Broch : www.infinite-loop.dk
2) Article ‘Using nsurlprotocol for injecting test data’