XCTest: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Parameter "test" must not be nil.' XCTest: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Parameter "test" must not be nil.' xcode xcode

XCTest: Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Parameter "test" must not be nil.'


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).

Horror

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 😱    }}

Solution

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")