【问题标题】:XCTestAssertNil crash due to "nil" parameterXCTestAssertNil 由于“nil”参数而崩溃
【发布时间】:2015-09-08 03:31:59
【问题描述】:

我正在使用 XCTest 在我的项目中编写单元测试,当使用 XCAssertNil()XCAssertNotNil() 方法时,XCTest 框架崩溃。

这是我的测试:

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

这是堆栈跟踪:

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

似乎 XCTest 有一个名为 test 的参数,它不能为 nil,这对于预期检查 nil(或非 nil)值的方法来说很奇怪......有其他人遇到这个问题并解决了吗?

【问题讨论】:

  • 我遇到了同样的错误,但情况不同。我认为问题在于我巧妙地滥用了测试 API —— 进行异步测试,并尝试在调用expectation.fulfill() 之后使用XCTAssertEqual 。我的猜测是测试框架没有注意到真正的问题,然后由于看似无关的原因而崩溃。
  • 是的 - 当您调用 expectation.fulfill() 然后订购一些异步代码时,XCTestCase 可能会被卸载。在@MattFenwick 下方查看我的答案
  • 昨天,我在使用 XCAssertNotNil() 和 XCAssertTrue() 函数时遇到了相同的“异常 'NSInternalInconsistencyException',原因:'参数“test”不能为 nil。'”错误。奇怪的是,这些测试已经使用了几个星期,但是当我更改了我一直在测试的函数中的一个参数时,它就开始了。而且这也是一个亮点:异常之后的任何测试都不会运行。我终于解决了这个问题,对项目进行了清理,丢弃了 DerivedData 中的文件夹并重新启动计算机。 Xcode 9.2,顺便说一句。

标签: ios xcode swift xctest


【解决方案1】:

根据这个 rdar http://www.openradar.me/22409527,这似乎是 XCTest 中的一个错误,当您检查一个为 nil 的可选项时会导致崩溃。

您可以使用以下方法修复您的测试:

XCTAssert(messageCollection.fieldName != nil, "field_name must be not-nil")

【讨论】:

  • 这似乎也不起作用,我仍然得到同样的错误。不过我使用的是 Xcode 8。
  • @MatthewDrill 您使用的是哪个版本的 Xcode?刚刚在 Xcode 8.2.1 中进行了测试,现在 XCTAssertNotNil() 可以按预期工作,至少对我来说是这样。 var optional: String?XCTAssertNotNil(optional, "field_name must be not-nil")
【解决方案2】:

正如我在 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);

它的第一个参数 - test - 指的是 XCTestCase 的实例。所以消息可能是:“嘿,你的 XCTestCase 对象不存在了,所以我不能调用它上面的任何方法”。

例如,当您在异步块中调用一些 XCTAssert... 时,可能会在您的封闭 XCTestCase 对象消失后很久才调用它。

如果可能是这种情况,将 [unowned self] 添加到您的 async 块并不能解决这里的问题,您需要使用 Expectations 或同步您的代码。

【讨论】:

    【解决方案3】:

    由于您的“测试”为零,我猜您正试图从您作为助手编写的独立函数中调用XCAssertNil。 XCTest 断言将self 作为“测试”,因此它们不能在独立函数中。它们必须在方法中。尝试将您的辅助函数更改为方法。

    【讨论】:

    • 其实我已经在一个测试方法中了,我的其他测试功能如XCTAssertEqual都在正常工作...
    • 很奇怪。尝试在您的测试方法中移动 XCTAssertEqual。它在 XCTAssertNil 旁边有效吗?
    • 我什至没有注意到我是如何使用 XCTAsserts 将代码剪切成辅助函数的,这就是我迷恋的原因!谢谢@JonReid
    【解决方案4】:

    在类似的情况下发生了同样的错误:

    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)
    

    所以在实现期望后调用XCTAssert
    这当然是错的。

    【讨论】:

    • 对我来说同样的问题!
    【解决方案5】:

    您也可以在测试函数完成执行时收到此错误,但如果您有任何异步调用任何 XCTAssert。它会使你的测试崩溃。我有同样的问题...

    【讨论】:

      【解决方案6】:

      如果你在做一个异步,你需要使用一个期望:

      //PRIOR TO TEST<br>
      let validation = expectation(description: "FullFill")
      <br><br>
      //AFTER ASYNCH IS COMPLETED<br>
      validation.fulfill()
      
      //BOTTOM OF YOUR TEST<br>
      self.waitForExpectations(timeout: 10){ error in }
      

      【讨论】:

        猜你喜欢
        • 2011-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-12
        • 1970-01-01
        • 1970-01-01
        • 2021-09-16
        相关资源
        最近更新 更多