是否有一种传统的方法来编写等待CloudKit查询完成的单元测试?

时间:2016-11-21 01:41:06

标签: swift xcode unit-testing asynchronous cloudkit

单元测试异步操作的传统方法是什么?

背景:

当我的应用程序初始化时,它会调用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)
    }
}

正如您所看到的,我通过在测试中插入一个睡眠来解决这个问题,但这种打击有点混乱,并且转向性能测试领域而不是单元测试。

是否有普遍接受的方法?

1 个答案:

答案 0 :(得分:3)

进行异步测试时,可以满足期望。您可以使用以下代码:

func testSomething() {
    let exp = expectation(description: "anAsyncCall")

    DoSomethingAsync() {
        exp.fulfill()
    }

    waitForExpectations(timeout: 10) { error in
        XCTAssertNil(error, "\(error)")
    }
}

在这种情况下,如果异步调用在10秒内完成,则测试将成功。