我尝试使用mockData对URLSession委托进行单元测试。这是正在测试的委托函数:
urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
到目前为止,这是单元测试:
func test_urlSession(){
let mockSession = MockURLSession(mockResponse: MockURLSession().successHttpURLResponse(request: self.urlRequest!) as! HTTPURLResponse)
//error here
sut?.urlSession(mockSession, task: MockURLSessionDataTask, didCompleteWithError: Error)
}
每当我尝试将mockURLSession作为参数注入错误:
无法调用非功能类型的值' URLSession'
我正在测试响应(即404,200),这就是为什么我用模拟响应注入mockURLSession的原因。有关如何将mockUrlSession注入委托的任何想法吗?
编辑___
protocol URLSessionDataTaskProtocol {
func resume()
}
protocol URLSessionProtocol {
typealias DataTaskResult = (Data?, URLResponse?, Error?) -> Void
func dataTask(with request: Request, completionHandler: @escaping DataTaskResult) -> URLSessionDataTaskProtocol
}
extension URLSession: URLSessionProtocol{
func dataTask(with request: Request, completionHandler: @escaping URLSessionProtocol.DataTaskResult) -> URLSessionDataTaskProtocol {
let task:URLSessionDataTask = dataTask(with: request, completionHandler: {
(data:Data?, response:URLResponse?, error:Error?) in completionHandler(data,response,error) }) as! URLSessionDataTask;
return task as URLSessionDataTaskProtocol
}
}
extension URLSessionDataTask: URLSessionDataTaskProtocol {}
class MockURLSession: URLSessionProtocol {
typealias DataTaskResult = (Data?, URLResponse?, Error?) -> Void
var nextDataTask = MockURLSessionDataTask()
var nextData: Data?
var nextError: Error?
private (set) var lastURL: URL?
private var mockResponse: HTTPURLResponse?
init() { }
init(mockResponse: HTTPURLResponse) {
self.mockResponse = mockResponse
}
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()
if let mockResponse = mockResponse {
completionHandler(nextData, mockResponse, nextError)
}
else {
//default case is success
completionHandler(nextData, successHttpURLResponse(request: request), nextError)
}
return nextDataTask
}
}
class MockURLSessionDataTask: URLSessionDataTaskProtocol {
private (set) var resumeWasCalled = false
func resume() {
resumeWasCalled = true
}
答案 0 :(得分:0)
委托方法的签名是
urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
因此第一个参数session
必须是URLSession类型。
当你可以控制一个函数的签名时,你可以说,“我们不要使用URLSession。让我们使用URLSessionProtocol。然后我们可以替换任何符合该协议的类型。”
但对于这种情况,情况并非如此。它必须是一个URLSession。
解决方法是使用部分模拟。创建一个继承自URLSession的测试double。我会说,“改变MockURLSession的基类,”但我不知道你是否在其他测试中使用它。您可能想要创建一个新的测试双精度来测试委托方法。
有关部分模拟的更多信息,请参阅https://qualitycoding.org/swift-partial-mock/