我想嘲笑URLSession,并返回一个嘲笑URLSessionDataTask。
为了模拟URLSession我创建一个协议
protocol URLSessionProtocol {
    func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask
}
然后可以URLSession在扩展中符合
extension URLSession: URLSessionProtocol {}
现在我想对 做同样的事情URLSessionDataTask,并为其实现类似的协议和扩展。我需要这样做,因为我调用的方式URLSession需要使用func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask
protocol URLSessionDataTaskProtocol {
    func resume()
}
extension URLSessionDataTask: URLSessionDataTaskProtocol {}
那么我的URLSessionDataTask模拟设置如下:
class URLSessionMock: URLSessionProtocol {
    typealias CompletionHandler = (Data?, URLResponse?, Error?) -> Void
    // data and error can be set to provide data or an error
    var data: Data?
    var error: Error?
    func dataTask(
        with url: URL,
        completionHandler: @escaping CompletionHandler
        ) -> URLSessionDataTask {
        let data = self.data
        let error = self.error
        return URLSessionDataTaskMock {
            completionHandler(data, nil, error)
        }
    }
}
我URLSessionDataTaskMock提出:
class URLSessionDataTaskMock: URLSessionDataTaskProtocol {
    private let closure: () -> Void
    init(closure: @escaping () -> Void) {
        self.closure = closure
    }
    // override resume and call the closure
    func resume() {
        closure()
    }
}
不起作用,因为URLSessionDataTaskMock内部URLSessionProtocol不是正确的返回类型 - 我需要返回一个URLSessionDataTask.
我无法将我的类型转换URLSessionDataTaskMock为URLSessionDataTask,因为类型不相关。
我怎样才能URLSessionDataTaskMock从我的归还我的URLSessionProtocol?
你也许可以摆脱这样的事情。关键是 URLSessionProtocol 中的关联类型
protocol URLSessionProtocol {
    associatedtype DataTaskType
    func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> DataTaskType
}
extension URLSession: URLSessionProtocol {}
protocol URLSessionDataTaskProtocol {
    func resume()
}
extension URLSessionDataTask: URLSessionDataTaskProtocol {}
class URLSessionDataTaskMock: URLSessionDataTaskProtocol {
    typealias CompletionHandler = URLSessionMock.CompletionHandler
    private let completion: CompletionHandler
    init(completion: @escaping CompletionHandler) {
        self.completion = completion
    }
    func resume() {
        // create some data
        completion(nil, nil, nil)
    }
}
class URLSessionMock: URLSessionProtocol {
    typealias CompletionHandler = (Data?, URLResponse?, Error?) -> Void
    // data and error can be set to provide data or an error
    var data: Data?
    var error: Error?
    func dataTask(
        with url: URL,
        completionHandler: @escaping CompletionHandler
    ) -> URLSessionDataTaskMock {
        return URLSessionDataTaskMock(completion: completionHandler)
    }
}
| 归档时间: | 
 | 
| 查看次数: | 1880 次 | 
| 最近记录: |