XCTest: Может ли ожидание выполнить для предиката при изменении асинхронной переменной? - PullRequest
0 голосов
/ 26 октября 2018

Я использую ожидание (для :otedWith: 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 голосов
/ 18 июля 2019

Я провел быстрое исследование своих тестов и заметил две вещи: 1. Как правильно говорит JD Wooder, вы должны наследовать свой производственный класс от NSObject (это то, что дает вам возможность вызывать методы времени выполнения obj-c и использоватьМетоды KeyValue).2. Тест больше не падает, но все равно не проходит.Чтобы исправить это, пометьте вашу переменную areWeDone с помощью спецификатора @objc (чтобы она выглядела как @objc var areWeDone).В моем случае это работает.

0 голосов
/ 18 июля 2019

Решение довольно простое - просто убедитесь, что класс «ProductionClass» наследуется от NSObject, и ваш тест будет работать как положено:

import Foundation

class ProductionClass : NSObject {
    var areWeDone = false

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