OCMock Tips & Tricks

Jasper Kuperus
May 11, 2014 · 2 min read

As a Java developer, I am currently struggling my way through iOS and Objective-C while developing an iPad app. My latest struggle with iOS and Objective-C was the combination of OCMock and XCTest. While the basics are quite similar to for instance Mockito and JUnit for Java, I ran into a few problems and distilled some tips and tricks from what I’ve learned.


Mock and verify a static method

Although the OCMock docs explicitly mention you need stub, you can mock a static method and still verify behaviour like this:

- (void)setUp()
{
self.myMock = [OCMockObject mockForClass:[MyClass class]];
[[[self.myMock expect] andReturnValue:5] myStaticMethod:3];
}

Now, you can test your code that depends on this static method, knowing it will return 5 when argument 3 is passed.

- (void)testMyStaticMethod
{
XCTAssertEqual(5, [MyClass methodThatCallsMyStaticMethod:3]);
[self.myMock verify];
}

The verify method now verifies that methodThatCallsMyStaticMethod internally called myStaticMethod with argument 3.


Stop Mocking Static Methods!

Normally if you stub a method, the stub will disappear with the deallocation of that instance. This is not the case for static methods. Therefore, you have to specifically tell OCMock to stop mocking that static method:

- (void)tearDown
{
[self.myMock stopMocking];
}

In my case, the test with the mocked class ran before the unit test of this class itself. This resulted in OCMock generating a Thread 1: EXC_BAD_ACCESS (code=2, address=0x7fff5f3ffff8) in its removeForwarderForClassMethodSelector: method whenever I tried using the mocked static method in the actual unit test for that class.


Return Primitive Values

Let’s say myStaticMethod returns NSInteger in stead of int. The above code will fail and give the following error message:

(5) equal to ([MyClass methodThatCallsMyStaticMethod:3]) failed: throwing “Return value does not match method signature; signature declares ‘q’ but value is ‘i’.”

If you modify your code to the following snippet, your code will work:

[[[self.myMock expect] andReturnValue:OCMOCK_VALUE((NSInteger){5})] myStaticMethod:3];

Any Argument for Primitives

For argument matching, OCMock provides the following syntax: [OCMArg any]. However, this does not work for primitive values. If you have primitive arguments and don’t want to or can’t define the specific arguments, use the following syntax:

[[[[self.myMock expect] ignoringNonObjectArgs] andReturnValue:OCMOCK_VALUE((NSInteger){5})] myStaticMethod:0];

The ignoringNonObjectArgs part simply tells OCMock to accept any primitive argument.


Use zero with ignoringNonObjectArgs

I experienced that mixing ignoringNonObjectArgs with non-zero arguments makes for unpredictable behaviour of OCMock. In my case, this resulted in the same scenario as mentioned at Stop Mocking Static Methods! So, make sure you use zero as an argument in this case:

// Bad!
[[[[self.myMock expect] ignoringNonObjectArgs] andReturnValue:OCMOCK_VALUE((NSInteger){5})] myStaticMethod:4];
// Good!
[[[[self.myMock expect] ignoringNonObjectArgs] andReturnValue:OCMOCK_VALUE((NSInteger){5})] myStaticMethod:0];

    Tech enthusiast

    Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
    Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
    Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade