Testing asynchronous code in XCTest
While writing tests in the app, I ran into the fact that tests containing asynchronous code did not work. For example, if we make an asynchronous network request and then verify the result inside the callback block. The assertions simply did not run, and Xcode said the test had passed successfully even when it obviously should not have.
While googling, I found two solutions: one via semaphores from Grand Central Dispatch, the other with expectations. I liked the expectations approach more. Example test:
import XCTest
class apiClientTests: XCTestCase {
override func setUp() {
super.setUp()
}
override func tearDown() {
super.tearDown()
}
/**
SampleTest
*/
func testSampleAsyncRequest() {
let exp = expectationWithDescription("\(#function)\(#line)")
APIClient.sharedInstance.someMethod { (responseObject, error) in
XCTAssertNotNil(responseObject, "responseObject should not be nil")
XCTAssertNil(error, "error should be nil")
exp.fulfill()
}
waitForExpectationsWithTimeout(40) { (error) in
if error != nil {
XCTAssertTrue(false)
}
}
}
}
P.S. — if you want tests to run in a specific order, remember that they are run in plain alphabetical order. So you need to name them test1Name, test2Name, and so on.