使用模拟数据测试 URLSession 委托
Test URLSession Delegates with mock data
我们有 2 个 URLSession 委托,它们在它们的主体中使用自定义代码(未显示以使此 post 更清晰):
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 class:
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 委托的最佳方法是什么?
您可以在初始化 MockURLSession
时注入模拟响应。
将以下内容添加到您的MockURLSession
:
private var mockResponse: HTTPURLResponse?
init() { }
init(mockResponse: HTTPURLResponse) {
self.mockResponse = mockResponse
}
修改您的模拟的 dataTask
函数以使用您的模拟响应调用完成处理程序,如果您提供的话:
if let mockResponse = mockResponse {
completionHandler(nextData, mockResponse, nextError)
}
else {
//default case is success
completionHandler(nextData, successHttpURLResponse(request: request), nextError)
}
现在,当您想要测试错误响应时,在创建模拟会话时将其注入:
let mockResponse = HTTPURLResponse(url: self.urlRequest.url!, statusCode: 404, httpVersion: "HTTP/1.1", headerFields: nil)!
let mockURLSession = MockURLSession(mockResponse: mockResponse)
调用 dataTask
时,将使用您的模拟响应:
mockURLSession.dataTask(with: self.urlRequest) { (data, response, error) in
if let response = response as? HTTPURLResponse {
print("Status Code: \(response.statusCode)") // "Status Code: 404"
}
}
我们有 2 个 URLSession 委托,它们在它们的主体中使用自定义代码(未显示以使此 post 更清晰):
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 class:
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 委托的最佳方法是什么?
您可以在初始化 MockURLSession
时注入模拟响应。
将以下内容添加到您的MockURLSession
:
private var mockResponse: HTTPURLResponse?
init() { }
init(mockResponse: HTTPURLResponse) {
self.mockResponse = mockResponse
}
修改您的模拟的 dataTask
函数以使用您的模拟响应调用完成处理程序,如果您提供的话:
if let mockResponse = mockResponse {
completionHandler(nextData, mockResponse, nextError)
}
else {
//default case is success
completionHandler(nextData, successHttpURLResponse(request: request), nextError)
}
现在,当您想要测试错误响应时,在创建模拟会话时将其注入:
let mockResponse = HTTPURLResponse(url: self.urlRequest.url!, statusCode: 404, httpVersion: "HTTP/1.1", headerFields: nil)!
let mockURLSession = MockURLSession(mockResponse: mockResponse)
调用 dataTask
时,将使用您的模拟响应:
mockURLSession.dataTask(with: self.urlRequest) { (data, response, error) in
if let response = response as? HTTPURLResponse {
print("Status Code: \(response.statusCode)") // "Status Code: 404"
}
}