Я использую ожидание (for: AssessmentWith: 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")
}
}
}
Решение довольно простое - просто убедитесь, что класс «ProductionClass» наследуется от NSObject, и ваш тест будет работать должным образом:
import Foundation
class ProductionClass : NSObject {
var areWeDone = false
func doSomeStuff() {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
self.areWeDone = true
}
}
}
Я быстро исследовал свои тесты и заметил две вещи:
1. Как правильно говорит Дж. Д. Вудер, вы должны унаследовать свой производственный класс от NSObject (это то, что дает вам возможность вызывать методы времени выполнения obj-c и использовать методы KeyValue).
2. Тест больше не вылетает, но все равно не проходит. Чтобы исправить эту отметку, ваша переменная areWeDone
со спецификатором @objc
(чтобы она выглядела как @objc var areWeDone
). В моем случае это работает.
В моем случае он работал без аннотации «@objc». Xcode 10.2.1, Swift 5