我正在XCode 9 gm上运行我的iOS应用程序的单元测试,其中几个因怪异的nsinternalinconsistencyException而失败,抱怨无法报告某些测试主张,因为牵连的测试没有关联的Xctestrun对象。我正在使用Ocmockito Ochamcrest进行嘲笑和调用验证。
出于演示目的,假设我的应用程序称为mytestapp,我有一个测试类脚步(从xctestcase继承)。在-setup中,我为测试创建并将各种模拟对象连接在一起,在 - teardown中,我将它们设置为nil,以防万一。
这是我得到的例外的一个示例:
2017-09-19 13:23:01.852729-0700 xctest [17006:5392130] ***断言失败在 - [脚步recordfailurewithDescription:infileWithDescription:infile:inline:trine:endire:]xctestrongim/xctest-13201/sources/xctestframework/core/xctestcase.m:308/users/foouser/workspaces/mytestapp/tests/footest.mm:135,因为它是在测试案例内提高的 - [togest testsomethingelse],它没有相关的xctestrun对象。这可能会发生在测试案例时发生,并在测试案例中构造和调用标准Xctest基础结构独立于标准xctest基础结构时。"(( 0 CoreFoundation 0X0000000102555D1CB __ ExceptionPreprocess 171 1 libobjc.a.dylib 0x0000000101ebff41 objc_exception_throw 48 2 Corefoundation 0x0000000102562362 [NSEXCEPTION RAISE:格式:参数:] 98 3基金会0x0000000101827089- [nsassertionhandler handlefailureInmethod:对象:文件:linenumber:lineNumber:description:] 193 4 xctest 0x0000000101D96875- [xctestcase recordfailureWithDescription:infile:inline:Expection:Expection:] 518 5 myAppunittests 0x000000011d7f2f5a- [HCXCTESTFAILURERERERERETER EXECUTEHANDLINGOFLURE:] 154 6 MyAppunittests 0x000000011d7f2b73- [Hctestfailurereererporter handlefailure:] 67 7 myAppunittests 0x000000011d64ec9a mktfailtest 217 8 myAppunittests 0x000000011d64c3f4- [mktexacttimes verifydata:] 254 9 MyAppunittests 0x000000011D64F2BA- [Mktbasemockobject verifyIfyInvocation:lustherVerificationMode:] 137 10 MyAppunittests 0x000000011D64F20B- [MKTBASEMOCKOBJECT HANDLINGVERIFYOFINVOCATION:] 115 11 MyAppunittests 0x000000011d64f15a- [Mktbasemockobject forwardenvocation:] 64 12 Corefoundation 0x00000001024DFED8 ___________ 760 13 CoreFoundation 0x00000001024DFB58 _CF_FORWARDGING_PREP_0 120 14 MyAppunittests 0x000000011C40B486- [脚部设置] 294 15 xctest 0x0000000101d97b39 __24- [xctestcase indoketest] _block_invoke_3 31 16 XCTEST 0x0000000101D97809 __24- [XCTESTCASE INDOKETEST] _BLOCK_INVOKE 271 17 xctest 0x0000000101ddff45- [xcuitestContext performInscope:] 183 18 xctest 0x0000000101D976EF- [XCTESTCASE INDOKETEST] 141
需要注意的几件事:
- 单元测试不是在XCtest Framework之外初始化Xctestcase或任何Xctest"基础结构"类。
- 受影响的单位测试的其余语句实际上被执行,直到例外。
- 所暗示的代码线看起来像:
[verify(_mockTestObject) description];
- 堆栈跟踪是关于问题发生的位置 - 它说它在-setup中,但是据我所知,Ocmockito只是在Next Next unite Test的运行开始时仅报告期望失败。问题位置(Footest.mm:135)看起来像以上验证()调用。
实际上,所有在此异常失败失败的单位测试失败,因为我们正在尝试验证一个模拟对象或另一个模拟对象是否已调用-[NSObject description]
。删除所有验证该呼叫的实例使测试通过。
我在Google上搜索了此特定的nsinternalInconSistencyException的其他实例,但没有产生任何结果。我不确定哪种方式 - [nSobject Description]与模拟对象上可以调用的任何其他方法不同 - 问题也可能不是真正存在的,但是它只是这种方式表现出来。我还试图找到是否可以为XCtest打开任何调试/诊断选项,以便我可以获得更多有关测试执行的详细记录信息,但我还没有找到类似的内容。
>对我接下来应该看的任何想法?非常感谢!
我在进行一些大型旧版代码测试时遇到了类似的问题。问题是:当您单独运行时,您的XCTExpectation
测试是否正常工作?如果是这样,这意味着在使用NSInternalInconsistencyException
测试之前执行的某些测试是在相关测试完成后以执行它们执行的方式派遣XCTest
相关方法。
看起来像(示例):
test1->派遣异步的"块",该块执行XCTFail
test1->完成
XCTFail
执行(但是test1通过,因为它在没有"失败"的情况下完成)或其他线程。
test2->用XCTExpectation
-> NSInternalInconsistencyException
Apple文档没有提供有关XCtest内部胆量的太多信息,但是我很确定这是问题所在。尝试按下故障排除步骤来限制测试"相互矛盾"(不XCTESTECTECTINE的不良内容,例如使用最终进行XCTest
断言,失败等的完成方法。):
- 在您的套房中进行二进制搜索:禁用一半的测试并使用您的
FooTest
运行套件。 - 如果您的测试套件运行可重新启用的一半残疾测试。如果测试套件在例外运行,则重新启用了所有禁用测试并禁用另一半。
- 重复步骤1,然后相对于剩余的较小测试。
- 最后,您最终将进行导致此例外的测试。
在我的情况下,有多次测试导致与XCTestExpectation
的冲突,因此搜索非常讨厌(套件为1000 XCTestCases
的套件几个小时,因此在5K测试中)。
然后彻底调查测试中发生的事情,与您的测试发生冲突。
可能是expectation.expectedFulfillmentCount
设置为较低的数字。
expectation.expectedFulfillmentCount = numberOfTimesCalled
您的numberOfTimesCalled
可能低于调用期望的次数。例如,您可以打电话两次,但是设置了一次期望。