Using OCMock 1.77 for Unit and Application Test with iOS4 and Xcode 4/SDK4.3

7

I am trying to use OCMock 1.77 for unit and application testing with iOS4 and Xcode 4/SDK4.3. I have followed the instructions to do using OCMock as a static library found here: http://www.mulle-kybernetik.com/software/OCMock/. The unit and application tests run fine without OCMock.

When I add OCMock and try to run OCMock's test suite for the simulator (unit tests), my test rig crashes with code 134. The test rig runs fine for a device (application tests). If I look in the console, I see the message below -- which suggests that I haven't added the -force_load linker flag per the instructions at the above URL. But I have... Any thoughts?

I looked at this: Test rig exited abnormally with code 134 with OCMock verify on iOS 4 which suggests this behavior is a bug -- but I'm not sure it is the same situation since I am running the OCMock test suite. If it is a bug, is there a work-around to use mocks in unit testing?

TIA.

=====

Console output:

3/30/11 1:02:32 AM  otest[38552]    *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '** Expected method not present; the method getArgumentAtIndexAsObject: is not implemented by NSInvocation. If you see this exception it is likely that you are using the static library version of OCMock and your project is not configured correctly to load categories from static libraries. Did you forget to add the -force_load linker flag?'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x004a05a9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x002cf313 objc_exception_throw + 44
    2   CoreFoundation                      0x00458ef8 +[NSException raise:format:arguments:] + 136
    3   CoreFoundation                      0x00458e6a +[NSException raise:format:] + 58
    4   LogicTests                          0x00f89de4 +[OCMockObject initialize] + 115
    5   libobjc.A.dylib                     0x002cfd9b _class_initialize + 380
    6   libobjc.A.dylib                     0x002d773f prepareForMethodLookup + 73
    7   libobjc.A.dylib                     0x002ce069 lookUpMethod + 86
    8   libobjc.A.dylib                     0x002ce1d6 _class_lookupMethodAndLoadCache + 40
    9   libobjc.A.dylib                     0x002e10e3 objc_msgSend + 87
    10  SenTestingKit                       0x20108824 +[NSObject(SenTestRuntimeUtilities) senAllSubclasses] + 107
    11  SenTestingKit                       0x201074a7 +[SenTestSuite updateCache] + 39
    12  SenTestingKit                       0x20107443 +[SenTestSuite suiteForBundleCache] + 92
    13  SenTestingKit                       0x201073a4 +[SenTestSuite testSuiteForBundlePath:] + 108
    14  SenTestingKit                       0x2010606b +[SenTestProbe specifiedTestSuite] + 332
    15  SenTestingKit                       0x20106792 +[SenTestProbe runTests:] + 156
    16  otest                               0x000023c7 0x0 + 9159
    17  otest                               0x000025f2 0x0 + 9714
    18  otest                               0x0000209a 0x0 + 8346
    19  otest                               0x00002049 0x0 + 8265
)
iphone
objective-c
xcode
ocmock
asked on Stack Overflow Mar 30, 2011 by Erik • edited May 23, 2017 by Community

2 Answers

8
  • Download OCMock *.** from http://ocmock.org/#download (At the moment of this writing 1.77)
  • unpack in a OCMock/ (or another folder) --> You will have two folder "Release" & "Source"
  • Copy the "Release/Library" folder inside your xCode project folder
  • Link your file with xcode dragging all the "Library" folder inside your porject
    • Select as the target the application TEST target!
  • Go to the "build settings" of your test target
    • Under "Search Paths" add: +"Header Search Paths" --> insert the path to your OCMock headers(.h) (something like $(PROJECT_DIR)/Library/Headers) +"Library Search Paths" --> insert the path to your OCMock library(.a) (something like $(PROJECT_DIR)/Library/) Note: as path you can also use $(PROJECT_DIR) or $(SRCROOT)/ and select the recursive checkbox to avoid insert the ocmplete path
      • Under "Linking" add: + "Other Link Flags" --> -all_load

Everything should now work correctly. To verifiy:

#import <OCMock/OCMock.h>
// simple test to ensure building, linking, 
// and running test case works in the project
- (void)testOCMockPass {
id mock = [OCMockObject mockForClass:NSString.class];
[[[mock stub] andReturn:@"mocktest"] lowercaseString];
NSString *returnValue = [mock lowercaseString];
STAssertEqualObjects(@"mocktest", returnValue, @"Should have returned the expected string.");
}

- (void)testOCMockFail {
id mock = [OCMockObject mockForClass:NSString.class];
[[[mock stub] andReturn:@"mocktest"] lowercaseString];
NSString *returnValue = [mock lowercaseString];
STAssertEqualObjects(@"thisIsTheWrongValueToCheck", returnValue, @"Should have returned the expected string."); 
}

Many thanks to:

Enrico Bottani

answered on Stack Overflow Sep 21, 2011 by Enrico Bottani • edited May 23, 2017 by Community
3

I can reproduce this by removing the -force_load flag. Check to make sure it's set on your test target, not your main target, and that it points to the correct location of the static library. In my case, that's

-force_load $(PROJECT_DIR)/Libraries/libOCMock.a

The other SO question you linked is just saying that when a mock's verify method fails, it throws an exception from a category method on NSInvocation, which causes otest to crash. It still works; the message is just more cryptic than an assertion failure, which XCode labels as an error in your test class.

answered on Stack Overflow Mar 30, 2011 by Christopher Pickslay • edited May 23, 2017 by Community

User contributions licensed under CC BY-SA 3.0