[swift-corelibs-dev] URLSession test fest!
paulstringer at mac.com
Fri Jan 27 02:51:29 CST 2017
First post and excited to join the party.
I'm sure this may have been solved many times over by the community already. Maybe we can collect some ideas on this. In the spirit of a small step to get things moving forward I'm sharing my own approach which has proven very effective for making URLSession extremely testable and it's amazingly little code with zero weirdness. All credit for the technique comes from Michael Feathers "Working Effectively with Legacy Code"
Here's the Gist:
And an explanation:
Leveraging the 'Subclass and Override Method' Technique I create a subclass e.g. 'NSURLSessionTestable'. I then expose any hidden dependancies using NSURLSession.sharedSession() in the code and make this dependancy injected to create a seam. Under test we are then able to substitute uses of sharedSession with an instance of NSURLSessionTestable.
NSURLSessionTestable is trivial in that we simply override dataTaskWithRequest() -> NSURLSessionDataTask()
The returned instance of NSURLSessionDataTask() does nothing. Instead we immediately invoke the completionHandler returning local instance variables of Data & URLResponse - these are provided by the test.
With this approach you have completely removed any network calls and asynchronous behaviour. This leads to extremely concise easy to setup and run tests.
It's so trivial I wonder if it would even be worth adding to the corelib - I'm personally a little wary of special 'knobs and dials' intended for making it more testable that could be hard to find or worse become used for doing odd stuff in production.
I've never seen any explicit 'Testable' classes so this would certainly mark a break from tradition but I personally have found the approach to work extremely well and through use of an explicitly named class it's intention revealing + easily discovered.
More information about the swift-corelibs-dev