Friday, February 12, 2016

Testing NSURLSession With Swift

Joe Masilotti:

Ideally, the interface to NSURLSession would be protocol based. We could create a mock object that conformed to this protocol and use the objects interchangeably under test.

Unfortunately, Apple hasn’t fully embraced protocol-oriented programming in its framework code. No worries; we’ll create our own protocol, and have NSURLSession conform to it via an extension.

[…]

We don’t actually have to implement anything in this extension because we kept the method signature the same as Apple’s framework. Meaning, NSURLSession already implements our protocols required methods.

[…]

The error is occurring because NSURLSession doesn’t have a dataTaskWithURL() method that returns our custom protocol. To fix this, we just need to extend the class a little differently.

[…]

Here we implement the method in the protocol manually. But instead of doing any actual work, we call back to the original implementation and cast the return value. The cast doesn’t need to be implicit because our protocol already conforms to Apple’s data task.

This is a subtle bit of code where the protocol and class have methods with the same name and arguments but different return types. So it’s an overload rather than an override.

Joe Masilotti:

To keep our tests running fast let’s completely flatten the code path. One thread, no asynchronous behavior, no network activity.

[…]

Now we can set what data and/or error is returned from the dataTaskWithURL() method. But wait, that method returns a data task, right? Correct, but look at the last parameter.

The completion handler would normally be called by the API when a real network request returns. We need to replicate this while we build our own mock. To do so, simply call the handler with our “next” variables before returning.

Previously: Swift Protocols.

Update (2016-11-12): Part 3.

Comments RSS · Twitter

Leave a Comment