Unit testing in Swift can be quite straightforward, especially when working with URLSession. To effectively test code that relies on network requests, you'll want to create a mock URLSession. This allows you to simulate network responses without making actual HTTP requests. Below, you will find an example of how to set up unit tests and mocks with URLSession in Swift.
import XCTest
import Foundation
// Define a protocol for URLSession to allow mocking
protocol URLSessionProtocol {
func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask
}
extension URLSession: URLSessionProtocol {
func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask {
return dataTask(with: url, completionHandler: completionHandler)
}
}
// Create a mock URLSession for testing
class MockURLSession: URLSessionProtocol {
var mockedData: Data?
var mockedError: Error?
func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask {
completionHandler(mockedData, nil, mockedError)
return URLSessionDataTask() // Return a dummy task
}
}
// Example network manager using URLSession
class NetworkManager {
var session: URLSessionProtocol
init(session: URLSessionProtocol = URLSession.shared) {
self.session = session
}
func fetchData(from url: URL, completion: @escaping (Data?, Error?) -> Void) {
session.dataTask(with: url) { data, response, error in
completion(data, error)
}.resume()
}
}
// Unit tests
class NetworkManagerTests: XCTestCase {
var networkManager: NetworkManager!
var mockSession: MockURLSession!
override func setUp() {
super.setUp()
mockSession = MockURLSession()
networkManager = NetworkManager(session: mockSession)
}
func testFetchData_Success() {
let expectedData = "Test data".data(using: .utf8)
mockSession.mockedData = expectedData
let expectation = self.expectation(description: "Completion Handler Called")
networkManager.fetchData(from: URL(string: "http://test.com")!) { data, error in
XCTAssertNil(error)
XCTAssertEqual(data, expectedData)
expectation.fulfill()
}
waitForExpectations(timeout: 1, handler: nil)
}
func testFetchData_Error() {
let expectedError = NSError(domain: "", code: 1, userInfo: nil)
mockSession.mockedError = expectedError
let expectation = self.expectation(description: "Completion Handler Called")
networkManager.fetchData(from: URL(string: "http://test.com")!) { data, error in
XCTAssertNotNil(error)
XCTAssertEqual((error as NSError?)?.code, 1)
expectation.fulfill()
}
waitForExpectations(timeout: 1, handler: nil)
}
}
How do I avoid rehashing overhead with std::set in multithreaded code?
How do I find elements with custom comparators with std::set for embedded targets?
How do I erase elements while iterating with std::set for embedded targets?
How do I provide stable iteration order with std::unordered_map for large datasets?
How do I reserve capacity ahead of time with std::unordered_map for large datasets?
How do I erase elements while iterating with std::unordered_map in multithreaded code?
How do I provide stable iteration order with std::map for embedded targets?
How do I provide stable iteration order with std::map in multithreaded code?
How do I avoid rehashing overhead with std::map in performance-sensitive code?
How do I merge two containers efficiently with std::map for embedded targets?