【问题标题】:How do I mock an Alamofire response only?如何仅模拟 Alamofire 响应?
【发布时间】:2016-05-10 17:44:15
【问题描述】:

我有使用 Alamofire 的 Swift 2 代码,它查询它期望返回 JSON 的远程 URL。我已经进行了足够多的交互式测试,以合理地确信它的行为足够正确。现在我想对它进行单元测试,这样我就可以依赖这段代码,然后再做其他事情。

我是 Swift 新手,虽然我已经编写 OO Perl 几十年了,所以我可能错过了一些东西。

到目前为止,这是我设置检查代码的方式(不重要的事情,例如我如何删除用户名和密码以避免牦牛剃须)。调用代码指定用户名和密码,并期望在获得结果时调用两个回调之一。 (我没有处理错误,所以请不要在这个问题上偏离轨道。)

struct checkUsernameHandler {
    var onSuccess: () -> ()
    var onFailure: () -> ()
}
struct checkUsernameOutput {
    var authenticated: Bool?
}

func checkUsername(user: User, handler: checkUsernameHandler) {
    Alamofire.request(.PUT, NSURL(string: baseURL + "/user/verify?key=" + apiKey)!,
        parameters: [
            "username": user.username!,
            "password": user.password!,
        ],
        encoding: .JSON
    ).responseJSON { response in
        let checkusernameOutput = self.analyseCheckUsernameResponse(response)
        if let authenticated = checkusernameOutput.authenticated {
            if authenticated {
                handler.onSuccess()
            } else {
                handler.onFailure()
            }
        }
    }
}

func analyseCheckUsernameResponse (response: Response<AnyObject, NSError>) -> checkUsernameOutput {
    var output = checkUsernameOutput()
    if (response.result.isSuccess) {
        if let JSON = response.result.value as? NSDictionary {
            // ...
        }
    } else {
        print("Didn't get proper JSON or something: \(response.result.error)")
    }
    return output
}

我正在寻找的是一种获取原始 JSON 并以某种方式将其传递给 Alamofire 的方法,因此我可以生成一个包含适当内容的响应对象,包括如果它没有得到任何东西时的错误(超时? ) 或返回的数据无效(例如 HTML 格式的 404 或 500 页面)。

我现在对函数 checkUsername 感到很满意,所以我对有人说“使用 OHHTTPStubs”不感兴趣。我正在考虑只测试我不确定的代码,也就是我刚刚编写的代码。

编辑:在搞砸了一些东西之后,看起来 Alamofire 的内部结构已经足够连接,可以创建一个虚假的响应,我需要做几乎所有涉及建立网络连接的工作无论如何。所以也许答案是“这样做太麻烦了”?

【问题讨论】:

标签: json swift unit-testing alamofire


【解决方案1】:

我通过重写 URLProtocol 的 startLoading 方法取得了成功。您可以在 URLProtocolTests.swift 下的 Alamofire 测试目录中找到一个示例。

通过拦截此调用,可以捕获传入请求,然后解析 URL 以匹配您选择的模拟响应。以下是我如何处理响应的示例:

override func startLoading() {
    //Seperate module I used to handle the request
    let data:NSData = mocks.find(request) as! NSData

    let client = self.client
    let response = HTTPURLResponse(url: (request.url)!, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: cannedHeaders)

    client?.urlProtocol(self, didReceive: response!, cacheStoragePolicy: URLCache.StoragePolicy.notAllowed)
    cannedResponse = data
    client?.urlProtocol(self, didLoad: cannedResponse as! Data)
    client?.urlProtocolDidFinishLoading(self)

    activeTask?.resume()
}

我在 github 上发布了一个完整的示例: https://github.com/ksteigerwald/MockAlamofire

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2017-10-09
  • 1970-01-01
  • 2015-06-26
  • 2015-05-03
  • 2017-05-23
  • 2013-03-23
  • 2014-10-08
  • 1970-01-01
相关资源
最近更新 更多