Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing primitives to an OCMock's stub

I'm learning how to use OCMock to test my iPhone's project and I have this scenario: a HeightMap class with a getHeightAtX:andY: method, and a Render class using HeightMap. I'm trying to unit test Render using some HeightMap mocks. This works:

id mock = [OCMockObject mockForClass:[Chunk class]];
int h = 0;
[[[mock stub] andReturnValue:OCMOCK_VALUE(h)] getHeightAtX:0 andY:0];

Of course, works only for x=0 and y=0. I want to test using a "flat" height map. This means I need to do something like this:

id chunk = [OCMockObject mockForClass:[Chunk class]];
int h = 0;
[[[chunk stub] andReturnValue:OCMOCK_VALUE(h)] getHeightAtX:[OCMArg any] andY:[OCMArg any]];

But this raises two compilation warnings:

warning: passing argument 1 of 'getHeightAtX:andY:' makes integer from pointer without a cast

and a runtime error:

unexpected method invoked: 'getHeightAtX:0 andY:0 stubbed: getHeightAtX:15545040 andY:15545024'

What am I missing? I found no way to pass a anyValue to this mock.

like image 582
Eduardo Costa Avatar asked Jun 12 '11 23:06

Eduardo Costa


5 Answers

It's been awhile since this question has been asked but I ran into this issue myself and couldn't find a solution anywhere. OCMock now supports ignoringNonObjectArgs so an example of an expect would be

[[[mockObject expect] ignoringNonObjectArgs] someMethodWithPrimitiveArgument:5];

the 5 doesn't actually do anything, just a filler value

like image 178
Andrew Park Avatar answered Nov 09 '22 04:11

Andrew Park


OCMock doesn't currently support loose matching of primitive arguments. There's a discussion about potential changes to support this on the OCMock forums, though it seems to have stalled.

The only solution I've found is to structure my tests in such a way that I know the primitive values that will be passed in, though it's far from ideal.

like image 18
Christopher Pickslay Avatar answered Nov 09 '22 04:11

Christopher Pickslay


Use OCMockito instead.

It supports primitive argument matching.

For instance, in your case:

id chunk = mock([Chunk class]);
[[given([chunk getHeightAtX:0]) withMatcher:anything() forArgument:0] willReturnInt:0];
like image 2
yonix Avatar answered Nov 09 '22 05:11

yonix


In addition to Andrew Park answer you could make it a little bit more general and nice looking:

#define OCMStubIgnoringNonObjectArgs(invocation) \
({ \
    _OCMSilenceWarnings( \
        [OCMMacroState beginStubMacro]; \
        [[[OCMMacroState globalState] recorder] ignoringNonObjectArgs]; \
        invocation; \
        [OCMMacroState endStubMacro]; \
    ); \
})

The you can use it like that:

OCMStubIgnoringNonObjectArgs(someMethodParam:0 param2:0).andDo(someBlock)

You can do the same for expecting. This case is for stubbing as topic starter request. It was tested with OCMock 3.1.1.

like image 1
Alex Avatar answered Nov 09 '22 04:11

Alex


You could do like this: id chunk = OCMClassMock([Chunk class]) OCMStub([chunk ignoringNonObjectArgs] getHeightAtX:0 andY:0]])

Readmore at: http://ocmock.org/reference/#argument-constraints

like image 1
Tan Vu Avatar answered Nov 09 '22 06:11

Tan Vu