XCTest:ExpectationForPredicate能否在异步变量更改上实现?

时间:2018-10-26 05:21:52

标签: ios swift unit-testing asynchronous xctestcase

我正在使用Expectation(for:evaluatedWith:handler :)监视生产代码中的变量以进行更改,但从未实现-为什么?

我不希望通过添加人工完成块或通知来弄乱我的生产代码。

class ProductionClass {
    var areWeDone = false

    func doSomeStuff() {
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
            self.areWeDone = true
        }
    }
}

class Test: XCTestCase {
    override func setUp() { }
    override func tearDown() { }

    func testDoSomeStuff() {
        let productionClass = ProductionClass()
        let predicate = NSPredicate(format: "areWeDone = %d", true)
        let exp = expectation(for: predicate, evaluatedWith: productionClass, handler: nil)

        productionClass.doSomeStuff()

        let result = XCTWaiter.wait(for: [exp], timeout: 3)
        if result != XCTWaiter.Result.completed {
            XCTAssert(false, "areWeDone changed but test timeout")
        }
   }
}

2 个答案:

答案 0 :(得分:0)

解决方案非常简单-只需确保“ ProductionClass”类是从NSObject继承的,并且您的测试即可按预期工作:

import Foundation

class ProductionClass : NSObject {
    var areWeDone = false

    func doSomeStuff() {
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
            self.areWeDone = true
        }
    }
}

答案 1 :(得分:0)

我对测试进行了快速研究,发现两件事:  1.就像J.D. Wooder正确说的那样,您应该从NSObject继承您的生产类(这使您有机会调用obj-c运行时方法并使用KeyValue方法)。  2.测试不再崩溃,但仍然失败。要解决此问题,请使用areWeDone说明符标记@objc变量(看起来像@objc var areWeDone)。就我而言,它有效。