Getting this error inconsistently when running some unit tests:
2018-12-20 09:11:34.892 MyApp[4530:106103] * Assertion failure in void _XCTFailureHandler(XCTestCase *__strong _Nonnull, BOOL, const char * _Nonnull, NSUInteger, NSString *__strong _Nonnull, NSString *__strong _Nullable, ...)(), /Library/Caches/com.apple.xbs/Sources/XCTest_Sim/XCTest-14460.20/Sources/XCTestFramework/Core/XCTestAssertionsImpl.m:41 2018-12-20 09:11:34.929 MyApp[4530:106103] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Parameter "test" must not be nil.'
Seems like some assertion is failing because a parameter is nil
, but I'm having a hard time figuring out which one.
Environment: Xcode 10.1 iOS application
XCTest
assertions that are evaluated after the test "finishes" will throw this exception if the assertion fails:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Parameter "test" must not be nil.'
A basic example to prove this is the following test:
func testRaceCondition() {
DispatchQueue.main.async {
XCTAssertEqual(1 + 1, 3) // Assertion fails and 'nil' exception is thrown 💥
}
}
The assertion is run asynchronously, but the test does not wait for the asynchronous block to finish. Thus, by the time the assertion is evaluated, the test has already finished and the test case has been released (and thus is nil
).
The above code will not throw any errors if the assertions were to pass. The following code would appear to pass the test, but it is dangerous in the sense that failures will throw the above exception, instead of properly failing the test:
func testRaceCondition() {
DispatchQueue.main.async {
XCTAssertEqual(1 + 1, 2) // Assertion passes 😱
}
}
To prevent this issue, all tests that evaluate assertions in a block executed asynchronously should use expectations and wait for them to complete:
func testRaceCondition() {
let asyncExpectation = expectation(description: "Async block executed")
DispatchQueue.main.async {
XCTAssertEqual(1 + 1, 3)
asyncExpectation.fulfill()
}
waitForExpectations(timeout: 1, handler: nil)
}
By using expectations, we will get a proper failing test error, instead of the hard-to-debug exception posted above:
XCTAssertEqual failed: ("2") is not equal to ("3")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With