How do i mock a method that accepts a handle as an argument in OCMock?
Asked Answered
A

5

19

I'm trying to mock a method that has the equivalent of the following signature:

- (NSDictionary *) uploadValues:(BOOL)doSomething error:(NSError **)error

I want it to return a small dictionary so that my test can make sure the code uses the dictionary properly. however, no matter what i do OCMock always returns nil from the method, regardless of how i stub it out. The error begins as nil in the code i'm testing, and these are the different ways i've tried stubbing it:

NSError * error = nil;
[[[mock stub] andReturn:someDict] uploadValues:YES error:&error];

[[[mock stub] andReturn:someDict] uploadValues:YES error:nil];

[[[mock stub] andReturn:someDict] uploadValues:YES error:[OCMArg any]];

and none of them work. Does OCMock support handles as stubbed message arguments and if so, what's the correct way to do it?

Avisavitaminosis answered 17/8, 2009 at 16:13 Comment(0)
F
-4

Sadly, I haven't found a good solution for this either. The best I can say is to try to make the use of the NSError** as small as possible, and then put it in an isolated function that you can completely mock out on your partial mock.

I'm finding that any code that uses anything other than an NSObject* (or derived) or primitive values (NSInteger, BOOL, etc) is pretty much impossible to test using OCMock.

Fonzie answered 9/12, 2009 at 22:1 Comment(2)
Using and providing methods that accept NSError ** is the preferred error handling mechanism in Cocoa. I suggest to stick with this paradigm and have a look at the answer from Andreas Järliden to mock these methods.Spirketing
See Andreas Järliden's answer below. Your answer is incorrect.Occupancy
N
49
[[[mock stub] andReturn:someDict] uploadValues:YES error:[OCMArg setTo:nil]];

or

NSError* someError = ...
[[[mock stub] andReturn:someDict] uploadValues:YES error:[OCMArg setTo:someError]];

You could also do

[[[mock stub] andReturn:someDict] uploadValues:YES error:[OCMArg anyPointer]];

but this might cause your code to incorrectly think that you passed back a real NSError.

Nickienicklaus answered 17/12, 2009 at 21:39 Comment(1)
In recent versions of OCMock, you can use [OCMArg anyObjectRef] instead of [OCMArg anyPointer] to avoid errors under ARC when you are dealing with pointers-to-pointers of Objective-C object types (such as NSError**).Coalfish
T
3

With ARC, your method declaration will probably look like this:

- (NSDictionary *) uploadValues:(BOOL)doSomething error:(NSError *__autoreleasing *)error;

Here is how I mock these types of methods:

BOOL mockDoSomething = YES;

NSError __autoreleasing *error = nil;

[[[mock stub] andReturn:someDict] uploadValues:OCMOCK_VALUE(mockDoSomething) error:&error];
Tamaru answered 9/8, 2012 at 23:26 Comment(1)
Specifically, the following seems to work just fine in an expect: error:((NSError __autoreleasing **)[OCMArg anyPointer])Bootjack
F
3
NSError *__autoreleasing *err = (NSError *__autoreleasing *) [OCMArg anyPointer];

[[[_mockReporter stub] andReturnValue:OCMOCK_VALUE((BOOL){YES})]
   yourMethodCall:err];
Fluky answered 6/3, 2013 at 17:54 Comment(0)
T
3

I created a category on OCMArg to aid with this situation.

OCMArg+Helpers.h:

@interface OCMArg (Helpers)

+ (NSError *__autoreleasing *)anyError;

@end

OCMArg+Helpers.m:

@implementation OCMArg (Helpers)

+ (NSError *__autoreleasing *)anyError {
    return (NSError *__autoreleasing *)[OCMArg anyPointer];
}

@end

Then, whenever I have an error param I need to mock, use anyError, like so:

[[myMock stub] someMethodWithArg:anArg error:[OCMArg anyError]];
Taiga answered 3/1, 2014 at 20:55 Comment(1)
Also, it looks like the latest version of OCMock on GitHub has something along these lines in OCMarg, + (id __autoreleasing *)anyObjectRef.Taiga
F
-4

Sadly, I haven't found a good solution for this either. The best I can say is to try to make the use of the NSError** as small as possible, and then put it in an isolated function that you can completely mock out on your partial mock.

I'm finding that any code that uses anything other than an NSObject* (or derived) or primitive values (NSInteger, BOOL, etc) is pretty much impossible to test using OCMock.

Fonzie answered 9/12, 2009 at 22:1 Comment(2)
Using and providing methods that accept NSError ** is the preferred error handling mechanism in Cocoa. I suggest to stick with this paradigm and have a look at the answer from Andreas Järliden to mock these methods.Spirketing
See Andreas Järliden's answer below. Your answer is incorrect.Occupancy

© 2022 - 2024 — McMap. All rights reserved.