I'm using expectation(for:evaluatedWith:handler:) to watch a variable in production code for a change, but it's never fulfilled - why?
I'd rather not clutter my production code by adding artificial completion blocks or notifications.
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")
}
}
}
The solution is quite easy - just make sure that the class "ProductionClass" inherits from NSObject and your test will work as expected:
import Foundation
class ProductionClass : NSObject {
var areWeDone = false
func doSomeStuff() {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
self.areWeDone = true
}
}
}