VIPER 中的 dataTaskWithURL 崩溃单元测试 swift 4

dataTaskWithURL crash unit testing in VIPER with swift 4

我正在关注 this tutorial 并尝试对我的 Web 服务进行单元测试。教程在swift2,我写在swift4。 我一切正常,但应用程序崩溃了,无论是单元测试还是 运行 应用程序,我都不知道为什么。有人可以帮忙吗?

崩溃的代码行是:

extension URLSession : URLSessionProtocol{
    func dataTaskWithURL(url: NSURL, completionHandler: (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTaskProtocol {

        return dataTaskWithURL(url: url, completionHandler: completionHandler) //app crash

    }
}

这是我的网络服务的完整代码:

import Foundation

protocol URLSessionProtocol {
    typealias DataTaskResult = (Data?, URLResponse?, Error?) -> Void

    func dataTaskWithURL(url: NSURL, completionHandler: DataTaskResult)
        -> URLSessionDataTaskProtocol
}
protocol URLSessionDataTaskProtocol {
    func resume()
}

class UserListRemoteDataManager:UserListRemoteDataManagerInputProtocol {

    var remoteRequestHandler: UserListRemoteDataManagerOutputProtocol?

    private let session : URLSessionProtocol

    init(session : URLSessionProtocol) {
        self.session = session
    }

    func retrieveUsers() {
        if let url = NSURL(string: Endpoints.Users.fetch.url){
            session.dataTaskWithURL(url: url, completionHandler: { (data, response, error) in
                if error != nil {
                    print(error as Any)
                }
                if error == nil && data != nil {
                    do{
                        let users = try JSONDecoder().decode(UserModel.self, from: data!)
                        self.remoteRequestHandler?.onUsersRetrieved(users.users)
                    }catch let error as NSError {
                        print(error)
                        self.remoteRequestHandler?.onError()
                    }
                }
            }).resume()
        }
    }
}
extension URLSession : URLSessionProtocol{
    func dataTaskWithURL(url: NSURL, completionHandler: (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTaskProtocol {

        return dataTaskWithURL(url: url, completionHandler: completionHandler) //app crash

    }
}
extension URLSessionDataTask : URLSessionDataTaskProtocol{

}

正如您所遵循的教程所解释的那样,URLSessionProtocol 的要点是复制您要测试的现有 URLSession 方法的函数签名。但是,您错误地更新了教程中的 Swift 2 代码,因此打破了这个假设。这导致 URLSession 没有自动符合 URLSessionProtocol 的问题,因此您尝试实际实现所需的协议方法,但协议并没有实际实现它,而是试图递归调用自身,导致无限递归.

您需要更改 URLSessionProtocol 的所需函数以完全匹配 URLSessiondataTask(with: <#T##URL#>, completionHandler: <#T##(Data?, URLResponse?, Error?) -> Void#>) 方法。

protocol URLSessionProtocol {
    typealias DataTaskResult = (Data?, URLResponse?, Error?) -> Void

    func dataTask(with: URL, completionHandler: DataTaskResult) -> URLSessionDataTask
}

那么你只需要声明协议一致性,但实际上不需要实现所需的方法,因为它已经由 URLSession:

实现了
 extension URLSession: URLSessionProtocol {}