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.