单元测试异步操作的传统方法是什么?
背景:
当我的应用程序初始化时,它会调用CloudKit并使用结果更新其内部数据源:
import Foundation
import CloudKit
class CountdownItemModel {
// MARK: - Properties
var countdownItems: [CountdownItem] = []
static let sharedInstance = CountdownItemModel()
let container: CKContainer
let database: CKDatabase
// MARK: - Initializers
init() {
container = CKContainer.default()
database = container.privateCloudDatabase
getAllCountdownItems()
}
// MARK - CloudKit Methods
func getAllCountdownItems() {
let query = CKQuery(recordType: "CountdownItem", predicate: NSPredicate(value: true))
database.perform(query, inZoneWith: nil) {
(results, error) in
if (error != nil) {
print("[ERROR] Error in getAllCountdownItems\n", error!)
}
else {
self.countdownItems.removeAll(keepingCapacity: true)
if let records = results {
for record in records {
let countdownItem = CountdownItem(record: record)
self.countdownItems.append(countdownItem)
}
}
}
}
}
}
使用X-Code的单元测试功能我已经编写了一个测试来检查来自iCloud的数据是否已经到达,但是此测试在查询返回之前运行,因此失败。
import XCTest
@testable import countdown
class countdownTests: XCTestCase {
let model = CountdownItemModel.sharedInstance
override func setUp() {
super.setUp()
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testItemsCountGreatThanZero() {
sleep(10) // <- DIRTY FIX/WORKAROUND
XCTAssert(model.countdownItems.count > 0)
}
}
正如您所看到的,我通过在测试中插入一个睡眠来解决这个问题,但这种打击有点混乱,并且转向性能测试领域而不是单元测试。
是否有普遍接受的方法?
答案 0 :(得分:3)
进行异步测试时,可以满足期望。您可以使用以下代码:
func testSomething() {
let exp = expectation(description: "anAsyncCall")
DoSomethingAsync() {
exp.fulfill()
}
waitForExpectations(timeout: 10) { error in
XCTAssertNil(error, "\(error)")
}
}
在这种情况下,如果异步调用在10秒内完成,则测试将成功。