簡體   English   中英

無法使用模擬URL會話調用非函數類型“ URLSession”的值錯誤

[英]Cannot call value of non-function type 'URLSession' error with mockURLSession

我正在嘗試使用模擬數據對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)
}

每當我嘗試將模擬URL會話作為參數注入時,都會出現錯誤:

無法調用非函數類型“ URLSession”的值

我正在測試響應(即404、200),這就是為什么要向模擬URL會話注入模擬響應。 關於如何將模擬UrlSession注入委托的任何想法嗎?

編輯___

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
    }

委托方法的簽名是

urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) 

因此,第一個參數session必須為URLSession類型。

當您可以控制函數的簽名時,可以說:“我們不要使用URLSession。讓我們使用URLSessionProtocol。然后,我們可以替換符合該協議的任何類型。”

但這不是這種情況。 它必須是URLSession。

解決方法是使用部分模擬。 進行一個繼承自URLSession的雙重測試。 我會說“更改MockURLSession的基類”,但是我不知道您是否在其他測試中使用它。 您可能需要創建一個新的測試double來測試委托方法。

有關部分模擬的更多信息,請參見https://qualitycoding.org/swift-partial-mock/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM