ios - 使用 swift 4 在 VIPER 中进行 dataTaskWithURL 崩溃单元测试

标签 ios swift unit-testing nsurlsession swift-protocols

我正在关注this tutorial并尝试对我的网络服务进行单元测试。该教程是 swift 2 中的,我已将其写入 swift 4 中。 我已经完成了所有操作,但应用程序崩溃了,无论我是在单元测试还是运行应用程序,我都不知道为什么。有人可以帮忙吗?

崩溃代码行是:

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

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

    }
}

这是我的 webService 的完整代码:

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 ,因此您尝试实际实现所需的协议(protocol)方法,但协议(protocol)并没有实际实现它,而是尝试递归调用自身,从而导致无限递归。

您需要更改URLSessionProtocol所需的功能完全匹配dataTask(with: <#T##URL#>, completionHandler: <#T##(Data?, URLResponse?, Error?) -> Void#>)方法URLSession .

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

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

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

 extension URLSession: URLSessionProtocol {}

关于ios - 使用 swift 4 在 VIPER 中进行 dataTaskWithURL 崩溃单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52706087/

相关文章:

swift - 弹出窗口演示从 xcode 7.3.1 中的手动/操作 segue 菜单中消失

python - Unittest中的一个文件中是否可以有2个测试类

unit-testing - Ember.js 中的单元测试

iOS PDFKit不会写

objective-c - 为什么 NSNumber 文字不能用于静态声明

ios - 在 WKWebView 中点击按钮后 UIButton 选择器不起作用

arrays - 从多维数组中删除重复项

swift - NSAttributedString 在初始化时崩溃,但为什么呢?

ios - 将分段控件添加到导航栏并使用按钮保留标题

unit-testing - 在 vuex Action 中模拟 api 调用