Question

When I set the return value of an NSInvocation to be an NSString, the invoker is receiving an NSCFString.

In my case I'm mocking to pull a bundle path from file included by unit tests:

[[[_bundlePartial stub] andDo:^(NSInvocation *invocation) {
    NSString* resourceName = [invocation getArgumentAtIndexAsObject:2];
    NSString* type = [invocation getArgumentAtIndexAsObject:3];
    NSString* path = [[NSBundle bundleForClass:self.class] pathForResource:resourceName ofType:type];
    if (!path)
    {
        path = [_bundleOriginal pathForResource:resourceName ofType:type];
    }
    [invocation setReturnValue:(void*)path];
}] pathForResource:OCMOCK_ANY ofType:OCMOCK_ANY];

I call it like this:

NSString* jsonPathInBundle = [[NSBundle mainBundle] pathForResource:self.fileName ofType:self.fileExtension];

Unfortunately I'm getting back a NSCFString. This makes some sense, since my NSString is backed by a NSCFString, but when I lose the bridge I can no longer call NSString instance methods on the object. Is there a way I can return the value as an NSString?

Was it helpful?

Solution

After examine the OCMock code, I found my problem. Effectively a typo but its subtle enough that I don't think it's worth deleting the question.

Change:

[invocation setReturnValue:(void*)path];

To:

[invocation setReturnValue:&path];

My original way of writing this destroyed a layer of abstraction because the NSString was being treated as an address, rather than using its actual address.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top