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

蓝咒 提交于 2019-12-11 14:48:56

问题


I'm trying to unit test URLSession delegates with mockData. This is the delegate function that is being tested:

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

This is the unit test so far:

 func test_urlSession(){

     let mockSession = MockURLSession(mockResponse: MockURLSession().successHttpURLResponse(request: self.urlRequest!) as! HTTPURLResponse)

                    //error here
    sut?.urlSession(mockSession, task: MockURLSessionDataTask, didCompleteWithError: Error)
}

Whenever I try to inject the mockURLSession as a parameter the error:

Cannot call value of non-function type 'URLSession'

I'm testing for responses (ie 404, 200) that's why I'm injecting the mockURLSession with mocked responses. Any idea on how to inject the mockUrlSession into the delegate?

Edit___

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
    }

回答1:


The signature of the delegate method is

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

So the first argument, session, must be of type URLSession.

When you can control the signature of a function, then you can say, "Let's not use URLSession. Let's use URLSessionProtocol instead. Then we can substitute any type that conforms to that protocol."

But that's not the true for this case. It has to be an URLSession.

The workaround is to use partial mocking. Make a test double that inherits from URLSession. I would say, "Change MockURLSession's base class," but I don't know if you're using it in other tests. You may want to create a new test double to test the delegate method.

For more on partial mocking, see https://qualitycoding.org/swift-partial-mock/



来源:https://stackoverflow.com/questions/49866777/cannot-call-value-of-non-function-type-urlsession-error-with-mockurlsession

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!