Discussion of the OCMock framework. If you have patches we would prefer you to send them to the mailing list, but attaching them to a topic is possible, too.


Postby harryb » 18 Oct 2010, 16:57

I am finding that I cannot use some of the block-based functionality on OCMockRecorder. I'm getting exceptions that the object doesn't respond to the selector andDo:. Initially I thought that I might be writing the test incorrectly, so I lifted one of the passing tests from the OCMock source project and put it into my own project. Here's what the test looks like:

Code: Select all
    describe(@"OCMock", ^{
        it(@"should support blocks", ^{
            /* This test passes in the OCMock source project. */
            void (^theBlock)(NSInvocation *) = ^(NSInvocation *invocation)
                NSString *value;
                [invocation getArgument:&value atIndex:2];
                value = [NSString stringWithFormat:@"MOCK %@", value];
                [invocation setReturnValue:&value];
            id mock = [OCMockObject mockForClass:[NSString class]];
            [[[mock stub] andDo:theBlock] stringByAppendingString:[OCMArg any]];
            assertThat([mock stringByAppendingString:@"foo"], is(@"MOCK foo"));
            assertThat([mock stringByAppendingString:@"bar"], is(@"MOCK bar"));

And the exception that is thrown:

Code: Select all
.2010-10-18 09:22:43.674 UISpecs[78953:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSProxy doesNotRecognizeSelector:andDo:] called!'
*** Call stack at first throw:
0   CoreFoundation                      0x0137abe9 __exceptionPreprocess + 185
1   libobjc.A.dylib                     0x014cf5c2 objc_exception_throw + 47
2   CoreFoundation                      0x01333628 +[NSException raise:format:arguments:] + 136
3   CoreFoundation                      0x0133359a +[NSException raise:format:] + 58
4   Foundation                          0x001f844b -[NSProxy doesNotRecognizeSelector:] + 74
5   CoreFoundation                      0x012ec366 ___forwarding___ + 966
6   CoreFoundation                      0x012ebf22 _CF_forwarding_prep_0 + 50
7   UISpecs                             0x0005ef41 __-[AppDelegateSpec declareBehaviors]_block_invoke_6 + 326
8   UISpecs                             0x00061703 -[CDRExample run] + 89

I am using the BDD framework Cedar for iPhone development. Cedar ships with a static library for OCMock, but not the one that you've provided in version 1.70. I attempted to replace Cedar's static library with the included one, but was having trouble getting anything to work. I rebuilt OCMock from source after changing the base SDK in the OCMockPhoneSim target to iOS 4.2 and the iOS deployment target to iOS 4.0, which seemed to resolve most issues.

My guess is that I did something wrong in rebuilding the library, and that the library was built in a state where NS_BLOCKS_AVAILABLE was false. If that's the case, the andDo: selector wouldn't be included in the library, would it?

When I run the tests, all of the blocks-enabled tests run and pass. My own project obviously supports blocks, as Cedar BDD is completely dependent upon their presence. I'm at a loss for how to proceed from here; any suggestions?

Posts: 2
Joined: 18 Oct 2010, 16:54

Re: doesNotRecognizeSelector:andDo

Postby erik » 21 Oct 2010, 09:18

From the error message you're getting I would arrive at the same conclusion, i.e. that the library in use is compiled without support for blocks. That said, I have no idea why that would be the case.

First, can you ensure that the library you are building from source is built with support for blocks? A quick way to verify is to use the otool command line tool on the library and search in the output for the name of the selector, ie. "andDo:".

Code: Select all
otool -o -V libOCMock.a

I've just double-checked that a library I'm building with SDK 4.1 for a 3.2 deployment platform does include the selector.

Next, you need to rebuild the BDD library that uses OCMock. It's a static library and the binary from the OCMock library will be linked (copied) into the binary for the BDD library. (Sorry if I'm stating the obvious.) It would be worth checking with otool whether the right bits of OCMock end up in the BDD library's binary.

Hopefully this solved your problem. This is all unnecessary fiddly but we only have Apple to thank for not allowing frameworks on iOS devices, and for having problems with Objective-C and static libraries.
Posts: 90
Joined: 10 Oct 2009, 15:22
Location: Hamburg, Germany

Return to OCMock