使用Swift 4在VIPER中进行dataTaskWithURL崩溃单元测试

时间:2018-10-08 15:59:06

标签: ios swift unit-testing nsurlsession swift-protocols

我正在关注this tutorial,并试图对我的Web服务进行单元测试。本教程位于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{

}

1 个答案:

答案 0 :(得分:0)

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

您需要更改URLSessionProtocol的必需功能以与dataTask(with: <#T##URL#>, completionHandler: <#T##(Data?, URLResponse?, Error?) -> Void#>)的{​​{1}}方法完全匹配。

URLSession

然后,您只需要声明协议一致性,而实际上不需要实现所需的方法,因为protocol URLSessionProtocol { typealias DataTaskResult = (Data?, URLResponse?, Error?) -> Void func dataTask(with: URL, completionHandler: DataTaskResult) -> URLSessionDataTask } 已经实现了该方法:

URLSession