TestingMidOpen-ended

How do you test network code without hitting a real server?

Explanation & Code

Answer: Use a custom URLProtocol subclass that intercepts URLSession requests and returns fake responses — no network needed, tests run instantly.

Code Example:

class MockURLProtocol: URLProtocol {
    static var mockData: Data = Data()
    static var mockStatusCode: Int = 200

    override class func canInit(with request: URLRequest) -> Bool { true }
    override class func canonicalRequest(for request: URLRequest) -> URLRequest { request }

    override func startLoading() {
        let response = HTTPURLResponse(
            url: request.url!,
            statusCode: MockURLProtocol.mockStatusCode,
            httpVersion: nil,
            headerFields: nil
        )!
        client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
        client?.urlProtocol(self, didLoad: MockURLProtocol.mockData)
        client?.urlProtocolDidFinishLoading(self)
    }

    override func stopLoading() {}
}

// In test setup
let config = URLSessionConfiguration.ephemeral
config.protocolClasses = [MockURLProtocol.self]
let session = URLSession(configuration: config)

// Inject into service
MockURLProtocol.mockData = try! JSONEncoder().encode([Article.mock()])
let service = ArticleService(session: session)
let articles = try await service.fetchArticles()
XCTAssertEqual(articles.count, 1)

Rate your understanding:

Ready to practice more Testing?

Test yourself with our interactive quiz mode or browse all curated questions for this topic.