david blogs
iPhone, blackberry, MS CRM, Java, Objective C
Wednesday, March 20, 2024
ITMS-91053: Missing API declaration - Your app’s code in the file references one or more APIs that require reasons, including the following API categories: NSPrivacyAccessedAPICategoryUserDefaults
Monday, March 4, 2024
Swift Rule Engine using Javascript for your iOS/MacOS application
Tuesday, February 27, 2024
Swift async/await - Sample API module with Unit test
Create Swift Package
In Xcode Menu, choose New -> Package from file menu.platforms: [
.iOS(.v13),
.macOS(.v12)
]
To consume the session tasks, we need url requests, for example assume our app have a feature to fetch the contacts from server. Also modify the getMyContacts() func.public func getMyContacts() async throws -> [Contact] {
let contactRequest = ContactEndPoint.myContacts.url(baseURL: baseURL)
let (data, httpResponse) = try await client.performRequest(contactRequest)
return try ContactDataMapper.map(data, from: httpResponse)
}
Create New Unit Test Case
Create protocol HTTPURLSession
And in the HttpClient class, change the type of session variable as HTTPURLSession.public protocol HTTPURLSession {
func data(for request: URLRequest) async throws -> (data: Data, response: HTTPURLResponse)
}
func test_init_doesNotExecuteURLRequest() async {
let (_, session) = makeSUT()
let executedUrls = session.executedURLs
XCTAssertTrue(executedUrls.isEmpty)
}
func test_deliverConnectivityErrorOnClientError() async throws {
let (sut, _) = makeSUT()
do {
_ = try await sut.getMyContacts()
} catch let error {
XCTAssertEqual((error as? APIError), APIError.connectivity)
return
}
XCTFail()
}
func test_deliverErrorOnInvalidJSONWith200Status() async throws {
let url = URL(string: "https://aurl.com")!
let (sut, session) = makeSUT(url: url)
let myContactURL = ContactEndPoint.myContacts.url(baseURL: url).url!
let invalidJSON = """
[
{"contactsssss_ID" : 2 }
]
"""
session.setResponse((invalidJSON.data(using: .utf8)!, responseWithStatusCode(200, url: myContactURL)), for: myContactURL)
do {
_ = try await sut.getMyContacts()
} catch let error {
XCTAssertEqual((error as? APIError), APIError.invalidData)
return
}
XCTFail()
}
func test_load_DeliverErroFor400Status() async throws {
let url = URL(string: "https://aurl.com")!
let (sut, session) = makeSUT(url: url)
let myContactURL = ContactEndPoint.myContacts.url(baseURL: url).url!
session.setResponse(("".data(using: .utf8)!, responseWithStatusCode(400, url: url)), for: myContactURL)
do {
_ = try await sut.getMyContacts()
} catch let error {
XCTAssertEqual((error as? APIError), APIError.serverDefined("400"))
return
}
XCTFail()
}
func test_load_deliversSuccessWith200HTTPResponseWithJSONItems() async throws {
let url = URL(string: "https://aurl.com")!
let (sut, session) = makeSUT(url: url)
let validJSON = """
[
{"contact_ID" : 2 }
]
"""
let myContactURL = ContactEndPoint.myContacts.url(baseURL: url).url!
session.setResponse((validJSON.data(using: .utf8)!, responseWithStatusCode(200, url: url)), for: myContactURL)
do {
let contacts = try await sut.getMyContacts()
XCTAssertEqual(contacts.count, 1)
} catch {
XCTFail()
}
}
@MainActor func test_load_DeliverConnectivityErrorIfTaskIsCancelled() async throws {
let url = URL(string: "https://aurl.com")!
let (sut, session) = makeSUT(url: url)
let dataResponse = """
[
{"contact_ID" : 2 }
]
"""
let myContactURL = ContactEndPoint.myContacts.url(baseURL: url).url!
session.setResponse((dataResponse.data(using: .utf8)!, responseWithStatusCode(200, url: url)), for: myContactURL)
let exp = expectation(description: "Wait for load completion")
let task = Task {
do {
let contacts = try await sut.getMyContacts()
exp.fulfill()
XCTAssertEqual(contacts.count, 0)
} catch let error {
exp.fulfill()
XCTAssertEqual((error as? APIError), APIError.connectivity)
}
}
task.cancel()
await fulfillment(of: [exp])
}