【问题标题】:completion handler not getting called未调用完成处理程序
【发布时间】:2021-03-18 08:46:13
【问题描述】:

我从这个site 中学到了相当全面的方法。我对其进行了一些定制以包含一个转义闭包,但它没有被调用,并且我没有在调用者级别收到任何响应。

我在所有守卫中设置了断点,以查看它是否在某个级别退出,但到目前为止还没有任何线索。

func getUsers(_ completion: @escaping (String?, NSException?) -> Void) {
    guard let url = URL(string: "http://127.0.0.1:8080/employees") else {
        completion(nil, NSException(name: NSExceptionName(rawValue: "Error"), reason: "Error validating URL.", userInfo: nil))
        return
    }
    
    var request = URLRequest(url: url)
    request.httpMethod = "GET"
    
    URLSession.shared.dataTask(with: request) { data, response, error in
        guard error == nil else {
            print("1")
            completion(nil, NSException(name: NSExceptionName(rawValue: "Error"), reason: error?.localizedDescription, userInfo: nil))
            return
        }
        
        guard let data = data else {
            print("2")
            completion(nil, NSException(name: NSExceptionName(rawValue: "Error"), reason: "Did not receive data.", userInfo: nil))
            return
        }
        
        guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
            print("3")
            completion(nil, NSException(name: NSExceptionName(rawValue: "Error"), reason: "HTTP request failed.", userInfo: nil))
            return
        }
        
        do {
            guard let jsonObject = try JSONSerialization.jsonObject(with: data) as? [String: Any] else {
                completion(nil, NSException(name: NSExceptionName(rawValue: "Error"), reason: "Cannot convert data to JSON object.", userInfo: nil))
                return
            }
            guard let prettyJsonData = try? JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted) else {
                completion(nil, NSException(name: NSExceptionName(rawValue: "Error"), reason: "Cannot convert JSON object to Pretty JSON data.", userInfo: nil))
                return
            }
            guard let prettyPrintedJson = String(data: prettyJsonData, encoding: .utf8) else {
                completion(nil, NSException(name: NSExceptionName(rawValue: "Error"), reason: "Could print JSON in String.", userInfo: nil))
                return
            }
            
            print(prettyPrintedJson)
            completion("done", nil)
            
        } catch {
            completion(nil, NSException(name: NSExceptionName(rawValue: "Error"), reason: "Trying to convert JSON data to string.", userInfo: nil))
            return
        }
        
    }.resume()
}

用法

func testGetUsers() {
    userData.getUsers {
        print($0 ?? "result is nil")
        print($1?.name ?? "error is nil")
    }
}

Info.plist 设置

【问题讨论】:

  • 您是在真实的 iOS 项目中进行测试吗?这在操场上是行不通的。
  • 在 iOS 项目中是,调用者在单元测试中
  • 哦,我需要在单元测试中等待吗?
  • 当然,你必须使用期望。您的代码是异步的。测试在联网开始之前就结束了。
  • 参见stackoverflow.com/questions/38501012/…,但我无法想象 iPhone 如何拥有 localhost。

标签: ios urlsession


【解决方案1】:

在您的测试中,您将使用期望来等待调用闭包,例如

func testGetUsers() {
    let e = expectation(description: "testGetUsers")

    userData.getUsers {
        print($0 ?? "result is nil")
        print($1?.name ?? "error is nil")
        e.fulfill()
    }

    waitForExpectations(timeout: 10)
}

在大多数圈子中,网络请求不被视为单元测试。通常我们会“模拟”网络响应,只是测试我们的应用程序处理各种类型响应的能力。单元测试的目标不是测试与后端的集成,而是测试它如何处理各种理论响应。

【讨论】:

  • 感谢 Rob,这完全让我忘记了测试功能必须比网络调用更有效。
  • 是的,你是对的。是否有链接可以找到有关如何模拟网络的更多信息。我是来自 java 背景的新手,当我尝试查找模拟时遇到了一些困难
猜你喜欢
  • 2014-08-16
  • 1970-01-01
  • 1970-01-01
  • 2019-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多