erikdoe / ocmock

Mock objects for Objective-C
http://ocmock.org
Apache License 2.0
2.16k stars 606 forks source link

Experiencing Non-Deterministic Unit Test Failures Related to Mocked NSDictionary #370

Closed imann24 closed 1 year ago

imann24 commented 5 years ago

Hi, I'm seeing occasional unit test failures when running tests via xcodebuild. These tests all fail with the same error (see below)

I cannot reproduce when running unit tests via the Xcode UI and re-running the test suite typically yields no errors.

Xcode Version: 10.1 xcodebuild command: OCMock Version: 3.4.3

xcodebuild -workspace "<workspace>" -scheme "<unit test scheme>" -sdk appletvsimulator -destination 'platform=tvOS Simulator,name=Apple TV,OS=11.4' clean test || exit 1

Additional Context: Most of the test classes which exhibit these failures have mocking calls related to NSDictionary such as OCMPartialMock([NSMutableDictionary dictionary]) or OCMClassMock([NSDictionary class])

Error:

2019-01-28 22:54:50.228494-0800 xctest[35517:994001] +[__NSDictionaryM ocmock_replaced_ocmock_replaced___new:::::]: unrecognized selector sent to class 0x10fb6e3f0
2019-01-28 22:54:50.241866-0800 xctest[35517:994001] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[__NSDictionaryM ocmock_replaced_ocmock_replaced___new:::::]: unrecognized selector sent to class 0x10fb6e3f0'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000010f8a6a56 __exceptionPreprocess + 294
    1   libobjc.A.dylib                     0x000000010ef3c031 objc_exception_throw + 48
    2   CoreFoundation                      0x000000010f927b24 +[NSObject(NSObject) doesNotRecognizeSelector:] + 132
    3   CoreFoundation                      0x000000010f829108 ___forwarding___ + 1432
    4   CoreFoundation                      0x000000010f828ae8 _CF_forwarding_prep_0 + 120
    5   CoreFoundation                      0x000000010f82a53c __invoking___ + 140
    6   CoreFoundation                      0x000000010f82a3f4 -[NSInvocation invoke] + 308
    7   OCMock                              0x00000001250332a4 -[OCClassMockObject forwardInvocationForClassObject:] + 244
    8   CoreFoundation                      0x000000010f828e68 ___forwarding___ + 760
    9   CoreFoundation                      0x000000010f828ae8 _CF_forwarding_prep_0 + 120
    10  CoreFoundation                      0x000000010f82a53c __invoking___ + 140
    11  CoreFoundation                      0x000000010f82a3f4 -[NSInvocation invoke] + 308
    12  OCMock                              0x00000001250332a4 -[OCClassMockObject forwardInvocationForClassObject:] + 244
    13  CoreFoundation                      0x000000010f828e68 ___forwarding___ + 760
    14  CoreFoundation                      0x000000010f828ae8 _CF_forwarding_prep_0 + 120
    15  CoreFoundation                      0x000000010f7b6cd4 -[__NSPlaceholderDictionary initWithCapacity:] + 116
    16  Foundation                          0x000000010e800ec2 -[NSKeyedArchiver _initWithOutput:] + 390
    17  Foundation                          0x000000010e8b1563 -[NSKeyedArchiver(NSKeyedArchiverSecureCodingInitializers) initRequiringSecureCoding:] + 33
    18  Foundation                          0x000000010e8b15ce +[NSKeyedArchiver(NSKeyedArchiverSecureCodingInitializers) archivedDataWithRootObject:requiringSecureCoding:error:] + 76
    19  DTXConnectionServices               0x000000011ced95a4 _withSerializedObject + 107
    20  DTXConnectionServices               0x000000011ced98f1 -[DTXMessage initWithInvocation:] + 530
    21  DTXConnectionServices               0x000000011cec26ee -[DTXProxyChannel _sendInvocationMessage:] + 141
    22  CoreFoundation                      0x000000010f828e68 ___forwarding___ + 760
    23  CoreFoundation                      0x000000010f828ae8 _CF_forwarding_prep_0 + 120
    24  XCTest                              0x000000010ee3dcb7 -[XCTRunnerIDESession logDebugMessage:] + 94
    25  XCTest                              0x000000010edb2d11 __32-[XCTestDriver logDebugMessage:]_block_invoke + 113
    26  libdispatch.dylib                   0x0000000112f876cb _dispatch_call_block_and_release + 12
    27  libdispatch.dylib                   0x0000000112f88709 _dispatch_client_callout + 8
    28  libdispatch.dylib                   0x0000000112f90142 _dispatch_queue_serial_drain + 735
    29  libdispatch.dylib                   0x0000000112f9093f _dispatch_queue_invoke + 321
    30  libdispatch.dylib                   0x0000000112f92c88 _dispatch_root_queue_drain + 473
    31  libdispatch.dylib                   0x0000000112f92a51 _dispatch_worker_thread3 + 119
    32  libsystem_pthread.dylib             0x00000001134ad6dd _pthread_wqthread + 619
    33  libsystem_pthread.dylib             0x00000001134ad405 start_wqthread + 13
)
erikdtw commented 5 years ago

This does look like a bug, and at the moment I have no explanation as to where the ocmock_replaced_ocmock_replaced___new comes from. It tries to invoke this selector but that could easily be a side effect from (erroneously) having redirected the new method twice.

One thing I wonder, if I read the stack trace correctly, the problem occurs during the logging of a message. Is it fair to assume that this is not part of the actual test? Do the crashes stop if you comment out the logging?

imann24 commented 5 years ago

Hi, pardon the delayed response. And thanks very much for the guidance.

To clarify, this crash is occurring within the test itself not from logging I've added. I've verified there are no invocations of NSLog in the failing test and I can still observe failures if I add the -quiet flag to my xcodebuild command

It's somewhat opaque to me exactly where the crash is occurring, since it's only reproducible from the command line