有没有一种传统的方法来编写等待 CloudKit 查询完成的单元测试?
Is there a conventional way to write a unit test that waits for a CloudKit query to complete?
单元测试异步操作的常规方法是什么?
背景:
当我的应用程序初始化时,它会调用 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)
}
}
如您所见,我已经通过在测试中插入睡眠来解决这个问题,但这看起来有点混乱,并且转向了性能测试领域而不是单元测试领域。
对此是否有普遍接受的方法?
在做异步测试的时候,可以满怀期待地工作。您可以使用这样的代码:
func testSomething() {
let exp = expectation(description: "anAsyncCall")
DoSomethingAsync() {
exp.fulfill()
}
waitForExpectations(timeout: 10) { error in
XCTAssertNil(error, "\(error)")
}
}
在这种情况下,如果异步调用在 10 秒内完成,则测试将成功。
单元测试异步操作的常规方法是什么?
背景:
当我的应用程序初始化时,它会调用 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)
}
}
如您所见,我已经通过在测试中插入睡眠来解决这个问题,但这看起来有点混乱,并且转向了性能测试领域而不是单元测试领域。
对此是否有普遍接受的方法?
在做异步测试的时候,可以满怀期待地工作。您可以使用这样的代码:
func testSomething() {
let exp = expectation(description: "anAsyncCall")
DoSomethingAsync() {
exp.fulfill()
}
waitForExpectations(timeout: 10) { error in
XCTAssertNil(error, "\(error)")
}
}
在这种情况下,如果异步调用在 10 秒内完成,则测试将成功。