HTTP Testing to the edge on iOS: The School of Hard Mocks
I’m a big fan of Automated Testing, even on iOS projects, but even when I was doing mostly Ruby, Java and C# work, I was never a big user of mock objects.
Now, I’ll admit that Mock objects can be useful under some circumstances, but I’ve seen them used too often in cases where a bunch of different developers each build their own little fiefdoms of their own code surrounded by Mock Objects where they interact with anything else. Each developer’s code runs perfectly when being tested against Mock input, but when you put all that code together, you can’t get a transaction working end-to-end, because the real world doesn’t obey the assumptions inherent in the Mocks.
So the Automated tests I write have more of a tendency to be more like what are called “Integration Tests”, even though I use “Unit Testing Frameworks” to write them.
When you combine that with the fact that I write a lot of iOS apps that talk to web servers, I want a way to test how my code talks to HTTP. And I want to know that my code handles things even when any library I happen to be using hands me errors to deal with.
When I first solved this problem years ago, we were using the Google Toolbox for Mac as our unit test framework, because SenTest didn’t work well back then. So, at the time, I built a solution based on GTM, but I went recently to try to recreate that solution for a new customer, and I realized that the files I had used had been deleted from GTM.
So I went spelunking back in the history of GTM, and pulled out the last version of the the files I needed before they were removed, and put them up on github in a new repository I’m calling SyntheticServerTest.
The way you use it is to look at the example test file.
You just have to run:
[testServer startServerWithDocumentRoot:]
With a document root directory that contains web content (I usually use ‘curl -O’ to pull known pages (either good or errors) from the server and write them to that directory), and have a mechanism so, that, while your test is running, the host part of the URL gets replaced with
@“localhost:%d”,[testServer port]
and the test HTTP server, running in the background (in the simulator or on the device), will get the HTTP request and hand you back the test data file in response.
This way, you can test your App’s entire HTTP stack, including any parsing libraries you may be using, with both real data (that doesn’t require you to be on line) and with bad data, to make sure you are correctly handling whatever errors your parsing or network library is throwing off.