XCTest:expectationForPredicate 能否实现异步变量更改?
XCTest: Can expectationForPredicate fulfill on async variable change?
我正在使用 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")
}
}
}
解决方案非常简单 - 只需确保 class "ProductionClass" 继承自 NSObject 并且您的测试将按预期工作:
import Foundation
class ProductionClass : NSObject {
var areWeDone = false
func doSomeStuff() {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
self.areWeDone = true
}
}
}
我对测试进行了快速研究,注意到两件事:
1. 点赞J.D。 Wooder 正确地说,您应该从 NSObject 继承您的生产 class(这使您有机会调用 obj-c 运行时方法并使用 KeyValue 方法)。
2. 测试不再崩溃但仍然失败。要修复此问题,请使用 @objc
说明符标记您的 areWeDone
变量(因此它看起来像 @objc var areWeDone
)。就我而言,它有效。
我正在使用 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")
}
}
}
解决方案非常简单 - 只需确保 class "ProductionClass" 继承自 NSObject 并且您的测试将按预期工作:
import Foundation
class ProductionClass : NSObject {
var areWeDone = false
func doSomeStuff() {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
self.areWeDone = true
}
}
}
我对测试进行了快速研究,注意到两件事:
1. 点赞J.D。 Wooder 正确地说,您应该从 NSObject 继承您的生产 class(这使您有机会调用 obj-c 运行时方法并使用 KeyValue 方法)。
2. 测试不再崩溃但仍然失败。要修复此问题,请使用 @objc
说明符标记您的 areWeDone
变量(因此它看起来像 @objc var areWeDone
)。就我而言,它有效。