Chapter 8 init() deprecated in iOS 13

Iโ€™m trying to create a similar mock class in page 153 ie mockSession: MockURLSession! and then initialised it in setup with mockSession = MockURLSession(). However i get a warning saying init() is deprecated in iOS 13.

Hi @alexhci, first than anything welcome to the community!

can you share the code of your mock?

override func setUp() {
    super.setUp()
    baseURL = URL(string: "https://example.com/api/v1")!
    mockSession = MockURLSession()
    sut = NetworkService()
}

override func tearDown() {
    baseURL = nil
    mockSession = nil
    sut = nil
    super.tearDown()
}

class MockURLSession: URLSession {
override func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) โ†’ Void) โ†’ URLSessionDataTask {
return MockURLSessionDataTask(completionHandler: completionHandler, url: url)
}
}

class MockURLSessionDataTask: URLSessionDataTask {
var completionHandler: (Data?, URLResponse?, Error?) โ†’ Void
var url: URL

init(completionHandler: @escaping (Data?, URLResponse?, Error?) โ†’ Void, url: URL) {
self.completionHandler = completionHandler
self.url = url
}

var calledResume = false
override func resume() {
calledResume = true
}
}

Just replicated the problem, Iโ€™ll take a look and let you know

Hi
Adding the super.init() gave me the following error:

โ€˜init()โ€™ was deprecated in iOS 13.0: Please use -[NSURLSession dataTaskWithRequest:] or other NSURLSession methods to create instances

@jrg.developer Can you please help with this when you get a chance? Thank you - much appreciated! :]

Does anyone have found a solution for this case?

Greetings. I know Iโ€™m kind of late to the party here, but I ran into the same deprecation and found a solution using a subclass of URLProtocol:

class URLProtocolMock: URLProtocol {
    /// Dictionary maps URLs to tuples of error, data, and response
    static var mockURLs = [URL?: (error: Error?, data: Data?, response: HTTPURLResponse?)]()

    override class func canInit(with request: URLRequest) -> Bool {
        // Handle all types of requests
        return true
    }

    override class func canonicalRequest(for request: URLRequest) -> URLRequest {
        // Required to be implemented here. Just return what is passed
        return request
    }

    override func startLoading() {
        if let url = request.url {
            if let (error, data, response) = URLProtocolMock.mockURLs[url] {
                
                // We have a mock response specified so return it.
                if let responseStrong = response {
                    self.client?.urlProtocol(self, didReceive: responseStrong, cacheStoragePolicy: .notAllowed)
                }
                
                // We have mocked data specified so return it.
                if let dataStrong = data {
                    self.client?.urlProtocol(self, didLoad: dataStrong)
                }
                
                // We have a mocked error so return it.
                if let errorStrong = error {
                    self.client?.urlProtocol(self, didFailWithError: errorStrong)
                }
            }
        }

        // Send the signal that we are done returning our mock response
        self.client?.urlProtocolDidFinishLoading(self)
    }

    override func stopLoading() {
        // Required to be implemented. Do nothing here.
    }
}

This allows us to override how URLSession handles requests and if the request url matches one that we have in the mockURLs dictionary, the error, and or data and response for that URL is returned when we do a dataTask(with:, completionHandler:):

        let url = URL(string: "https://github.com")
        let data = Data()
        let response = HTTPURLResponse(url: URL(string: "https://github.com")!, statusCode: 200, httpVersion: nil, headerFields: nil)
        URLProtocolMock.mockURLs = [url: (nil, data, response)]

        let sessionConfiguration = URLSessionConfiguration.ephemeral
        sessionConfiguration.protocolClasses = [URLProtocolMock.self]
        let mockSession = URLSession(configuration: sessionConfiguration)

        let task = mockSession.dataTask(with: url!, completionHandler: { (data, response, error) in
            XCTAssertNil(error)
            XCTAssertNotNil(data)
            guard let httpResponse = response as? HTTPURLResponse else {
                XCTFail("unexpected response")
                return
            }
            XCTAssertEqual(200, httpResponse.statusCode)
        })
        task.resume()
1 Like

@cdisdero Thank you for sharing your solution - much appreciated!