XCTest
утверждения, которые оцениваются после «завершения» теста, выдают это исключение в случае сбоя подтверждения:
Завершение приложения из-за неперехваченного исключения «NSInternalInconsistencyException», причина: тест «Parameter»«не должно быть ноль.»
Базовым примером, подтверждающим это, является следующий тест:
func testRaceCondition() {
DispatchQueue.main.async {
XCTAssertEqual(1 + 1, 3) // Assertion fails and 'nil' exception is thrown ?
}
}
Утверждение выполняется асинхронно, но тест не ожидаетасинхронный блок до конца.Таким образом, к моменту оценки утверждения тест уже завершен, и тестовый пример был освобожден (и таким образом равен nil
).
Ужас
Приведенный выше код не будет выбрасыватьлюбые ошибки, если утверждения должны были пройти.Следующий код может пройти тест, но он опасен в том смысле, что сбои вызовут вышеупомянутое исключение вместо правильного сбоя теста:
func testRaceCondition() {
DispatchQueue.main.async {
XCTAssertEqual(1 + 1, 2) // Assertion passes ?
}
}
Решение
Чтобы предотвратитьВ этом случае все тесты, которые оценивают утверждения в блоке, выполняемом асинхронно, должны использовать ожидания и ждать, пока они завершатся:
func testRaceCondition() {
let asyncExpectation = expectation(description: "Async block executed")
DispatchQueue.main.async {
XCTAssertEqual(1 + 1, 3)
asyncExpectation.fulfill()
}
waitForExpectations(timeout: 1, handler: nil)
}
Используя ожидания, мы получим правильную ошибочную ошибку теста вместо жесткойисключение для отладки, опубликованное выше:
Ошибка XCTAssertEqual: ("2") не равно ("3")