我如何仅模拟Alamofire回复?

时间:2016-02-02 03:45:29

标签: json swift unit-testing alamofire

我使用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的内部已经足够连接以创建一个虚假的响应,我需要做几乎所有与建立网络连接有关的工作反正。所以也许答案是“这样做太麻烦了”?

1 个答案:

答案 0 :(得分:5)

我通过覆盖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