Skip to content

Instantly share code, notes, and snippets.

@MounikaMadishetti
Created March 3, 2024 08:25
Show Gist options
  • Save MounikaMadishetti/36f860d7682cb443472733dcd5f65eec to your computer and use it in GitHub Desktop.
Save MounikaMadishetti/36f860d7682cb443472733dcd5f65eec to your computer and use it in GitHub Desktop.
Create URLProtocol subclass for intercepting network requests
// MARK: - Main Target
final class HTTPClient {
private let session: URLSession
init(session: URLSession = URLSession.shared) {
self.session = session
}
func get(from url: URL) {
session.dataTask(with: URLRequest(url: url)).resume()
}
}
// MARK: - Test Target
final class URLSessionHTTPClientTests: XCTestCase {
override func setUp() {
super.setUp()
URLProtocolStub.startInterceptingRequests()
}
override func tearDown() {
super.tearDown()
URLProtocolStub.stopInterceptingRequests()
}
func test_httpClient_loadsData() {
let data = Data(bytes: "anydata".utf8)
let url = URL(string: "https://www.any-url.com")!
let response = HTTPURLResponse(url: url, statusCode: 200, httpVersion: "", headerFields: nil)!
URLProtocolStub.stub(data: data, response: response, error: nil)
let sut = HTTPClient()
let expectation = expectation(description: "wait for completion")
sut.get(from: url) { result in
switch result {
case let .success(receivedData, receivedResponse):
XCTAssertEqual(receivedData, data)
XCTAssertEqual(receivedResponse.url, response.url)
XCTAssertEqual(receivedResponse.statusCode, response.statusCode)
default:
XCTFail("expected success receive \(result) instead")
}
expectation.fulfill()
}
wait(for: [expectation], timeout: 2.0)
}
}
class URLProtocolStub: URLProtocol {
static var stub: Stub?
struct Stub {
let data: Data?
let response: URLResponse?
let error: Error?
}
override class func canInit(with request: URLRequest) -> Bool {
return true
}
override class func canonicalRequest(for request: URLRequest) -> URLRequest {
request
}
override func startLoading() {
if let data = URLProtocolStub.stub?.data {
client?.urlProtocol(self, didLoad: data)
}
if let response = URLProtocolStub.stub?.response {
client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
}
if let error = URLProtocolStub.stub?.error {
client?.urlProtocol(self, didFailWithError: error)
}
client?.urlProtocolDidFinishLoading(self)
}
override func stopLoading() { }
static func stub(data: Data?, response: URLResponse?, error: Error? = nil) {
stub = Stub(data: data, response: response, error: error)
}
static func startInterceptingRequests() {
URLProtocol.registerClass(URLProtocolStub.self)
}
static func stopInterceptingRequests() {
URLProtocol.unregisterClass(URLProtocolStub.self)
stub = nil
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment