Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XCTestAssertNil crash due to "nil" parameter

I'm using XCTest to write unit tests in my project, and when using the XCAssertNil() or XCAssertNotNil() methods, XCTest framework crashes.

Here's my test:

XCTAssertNotNil(messageCollection.fieldName, "field_name must be not-nil")

Here's the stack trace:

2015-06-22 17:05:17.629 xctest[745:8747] *** Assertion failure in void _XCTFailureHandler(XCTestCase *, BOOL, const char *, NSUInteger, NSString *, NSString *, ...)(), /SourceCache/XCTest_Sim/XCTest-7701/XCTestFramework/OtherSources/XCTestAssertionsImpl.m:41
Test Case '-[Wakanda_iOS_Framework_Tests.WAKAdapterTest testEntityCollectionParsing]' started.
2015-06-22 17:05:17.631 xctest[745:8747] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Parameter "test" must not be nil.'

It seems that XCTest has a parameter named test which cannot be nil, strange for a method expected to check for nil (or non-nil) values... Does anyone else got this problem and solved it?

like image 635
sweepy_ Avatar asked Jun 22 '15 15:06

sweepy_


4 Answers

According to this rdar http://www.openradar.me/22409527, this seems to be a bug in XCTest, leading to a crash when you check an optional that is nil.

You can fix your test with:

XCTAssert(messageCollection.fieldName != nil, "field_name must be not-nil")
like image 138
florieger Avatar answered Oct 16 '22 10:10

florieger


As I see in XCTestAssertionsImpl.h:

XCT_EXPORT void _XCTFailureHandler(XCTestCase *test, BOOL expected, const char *filePath, NSUInteger lineNumber, NSString *condition, NSString * __nullable format, ...) NS_FORMAT_FUNCTION(6,7);

It's first argument - test - refers to the instance of XCTestCase. So the message might be: "Hey man, your XCTestCase object doesn't exist any more, so I cannot invoke any method on it".

It might be a case for example when you call some XCTAssert... in asynchronous block, that might be invoked long after your enclosing XCTestCase object has gone.

If that might be a case adding [unowned self] to your async block wont solve the issue here, you need to go for Expectations or synchronise your code.

like image 31
Maciek Czarnik Avatar answered Oct 16 '22 09:10

Maciek Czarnik


Since your "test" is nil, I'm guessing you're trying to call XCAssertNil from a standalone function you wrote as a helper. The XCTest assertions take self as "test", so they can't be in standalone functions. They must be in methods. Try changing your helper function to a method.

like image 36
Jon Reid Avatar answered Oct 16 '22 09:10

Jon Reid


Same error occured in a similar situation like this:

let expectation = self.expectation(description: "exp")

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    expectation.fulfill()
}

DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
    XCTAssert(false)
}

waitForExpectations(timeout: 2, handler: nil)

So calling XCTAssert after the expectation was fulfilled.
Which ofcourse is wrong.

like image 1
basvk Avatar answered Oct 16 '22 08:10

basvk