How to stub URLSession in Swift?
I have finally found the solution. It’s fascinating as we missed the wood for the trees. There are two issues:
1) It seems that Swift 4 has changed the signature for dataTask(with: NSURLRequest)
to dataTask(with: URLRequest)
Therefore the line in my opening question would only match to the Protocol's func signature, and it would never hit the dataTask
inside URLSession
, hence the infinite loop. To solve this issue I had to change NSURLRequest
to URLRequest
and refactor the code accordingly.
2) The signature remains vague, hence it is better to store the result as dataTask first with a cast to URLSessionDataTask
and then return the variable.
New refactored Code for Swift 4:
typealias DataTaskResult = (Data?, URLResponse?, Error?) -> Void
protocol URLSessionProtocol {
func dataTask(with request: URLRequest, completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskProtocol
}
extension URLSession: URLSessionProtocol {
func dataTask(with request: URLRequest, completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskProtocol {
let task:URLSessionDataTask = dataTask(with: request, completionHandler: {
(data:Data?, response:URLResponse?, error:Error?) in completionHandler(data,response,error) }) as URLSessionDataTask
return task
}
}
I also found I had to inject URLSession.shared
as a singleton and not as URLSession()
, otherwise it could crash.