Что делать, если XCTestExpectation является неожиданным
Я пишу модульный тест XCTest в Swift. Идея состоит в том, что обратный вызов не должен вызываться в определенном случае.
Так что я делаю, это
func testThatCallbackIsNotFired() {
let expectation = expectationWithDescription("A callback is fired")
// configure an async operation
asyncOperation.run() { (_) -> () in
expectation.fulfill() // if this happens, the test must fail
}
waitForExpectationsWithTimeout(1) { (error: NSError?) -> Void in
// here I expect error to be not nil,
// which would signalize that expectation is not fulfilled,
// which is what I expect, because callback mustn't be called
XCTAssert(error != nil, "A callback mustn't be fired")
}
}
Когда вызывается обратный вызов, все работает нормально: происходит сбой с сообщением " Обратный вызов не должен быть запущен ", что именно то, что мне нужно.
Но если ожидание не было выполнено, оно терпит неудачу и говорит
Ошибка асинхронного ожидания: Превышено время ожидания в 1 секунду с невыполненными ожиданиями: "Обратный вызов запущен".
Так как мне нужно неисполненное ожидание, я не хочу проваливать тест.
Есть ли у вас какие-либо предложения, что я могу сделать, чтобы избежать этого? Или, может быть, я могу достичь своей цели по-другому? Благодарю.
1 ответ
У меня была такая же проблема, и меня раздражает, что вы не можете использовать обработчик для переопределения сбоя тайм-аута waitForExpectationsWithTimeout. Вот как я это решил (синтаксис Swift 2):
func testThatCallbackIsNotFired() {
expectationForPredicate(NSPredicate{(_, _) in
struct Holder {static let startTime = CACurrentMediaTime()}
if checkSomehowThatCallbackFired() {
XCTFail("Callback fired when it shouldn't have.")
return true
}
return Holder.startTime.distanceTo(CACurrentMediaTime()) > 1.0 // or however long you want to wait
}, evaluatedWithObject: self, handler: nil)
waitForExpectationsWithTimeout(2.0 /*longer than wait time above*/, handler: nil)
}
Использование isInverted
как в этом посте https://www.swiftbysundell.com/posts/unit-testing-asynchronous-swift-code
class DebouncerTests: XCTestCase {
func testPreviousClosureCancelled() {
let debouncer = Debouncer(delay: 0.25)
// Expectation for the closure we'e expecting to be cancelled
let cancelExpectation = expectation(description: "Cancel")
cancelExpectation.isInverted = true
// Expectation for the closure we're expecting to be completed
let completedExpectation = expectation(description: "Completed")
debouncer.schedule {
cancelExpectation.fulfill()
}
// When we schedule a new closure, the previous one should be cancelled
debouncer.schedule {
completedExpectation.fulfill()
}
// We add an extra 0.05 seconds to reduce the risk for flakiness
waitForExpectations(timeout: 0.3, handler: nil)
}
}