【发布时间】:2018-04-13 09:49:40
【问题描述】:
我们有 2 个 URLSession 委托在其正文中使用自定义代码(未显示以使这篇文章更清晰):
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {}
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let error = error {
//code here
} else if let response = task.response as? HTTPURLResponse, var dataResponse = self.dataReceived {
if (400...499).contains(response.statusCode) {
//handle response here
}
}
我们有一个 mockURLSession 类:
protocol URLSessionDataTaskProtocol {
func resume()
}
protocol URLSessionProtocol {
typealias DataTaskResult = (Data?, URLResponse?, Error?) -> Void
func dataTask(with request: Request, completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskProtocol
}
class MockURLSession: URLSessionProtocol {
typealias DataTaskResult = (Data?, URLResponse?, Error?) -> Void
var nextDataTask = MockURLSessionDataTask()
var nextData: Data?
var nextError: Error?
private (set) var lastURL: URL?
func successHttpURLResponse(request: Request) -> URLResponse {
return HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: nil)!
}
func wrongHttpURLResponse(request: Request, statusCode:Int) -> URLResponse {
return HTTPURLResponse(url: request.url!, statusCode: statusCode, httpVersion: "HTTP/1.1", headerFields: nil)!
}
func dataTask(with request: Request, completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskProtocol {
lastURL = request.url
nextDataTask.resume()
completionHandler(nextData, successHttpURLResponse(request: request), nextError)
return nextDataTask
}
}
class MockURLSessionDataTask: URLSessionDataTaskProtocol {
private (set) var resumeWasCalled = false
func resume() {
resumeWasCalled = true
}
}
我们遇到的问题是我必须为来自模拟服务器的特定响应(例如 404)编写单元测试。通常我会这样写响应:
let urlReponse = MockURLSession().wrongHttpURLResponse(request: self.urlRequest!, statusCode: 404)
我遇到的问题是,因为我们使用的是 URLSession 委托,所以我无法将 mockResponse 作为参数注入到函数中,除非它不会被调用。基于模拟响应测试 URLSession 委托的最佳方法是什么?
【问题讨论】:
-
如果只想测试delegate,可以直接在你的测试用例中调用
标签: ios swift unit-testing urlsession