24

Is there a way to verify that a method has been called 'x' amount of times?

qnoid
  • 2,346
  • 2
  • 26
  • 45

3 Answers3

21

Looking at the test file for OCMock, it seems that you need to have the same number of expects as you have calls. So if you call someMethod three times, you need to do...

[[mock expect] someMethod];
[[mock expect] someMethod];
[[mock expect] someMethod];

...test code...

[mock verify];

This seems ugly though, maybe you can put them in a loop?

GoatInTheMachine
  • 3,583
  • 3
  • 25
  • 35
  • 5
    I think this only verifies that the method has been called at least 3 times, so it will also pass if it was called 4 times. – dB. Jan 22 '14 at 13:56
  • 1
    My testing with v2.2.3 shows that there needs to be an exact match between the number of expects and the number of calls to someMethod – Skotch Apr 03 '14 at 22:52
  • 3
    @dB & Skotch: this depends on the kind of Mock that you use - if you create a niceMock it expects 'at least' the number - for a usual mock it expects the exact number – Simon Meyer Jan 06 '15 at 14:50
  • 1
    I'm using OCMock 3.x and even when using a partial mock I don't get a failure when the # of calls is greater than expected. – ThomasW Apr 18 '16 at 06:06
13

I've had success by leveraging the ability to delegate to a block:

OCMStub([mock someMethod]).andDo(^(NSInvocation *invocation)
{ /* block that handles the method invocation */ });

Inside the block, I just increment a callCount variable, and then assert that it matches the expected number of calls. For example:

- (void)testDoingSomething_shouldCallSomeMethodTwice {
    id mock = OCMClassMock([MyClass class]);

    __block int callCount = 0;
    OCMStub([mock someMethod]).andDo(^(NSInvocation *invocation) {
        ++callCount;
    });

    // ...exercise code...

    int expectedNumberOfCalls = 2;
    XCTAssertEqual(callCount, expectedNumberOfCalls);
}

The block should be invoked each time someMethod is called, so callCount should always be the same as the number of times the method was actually called.

ThomasW
  • 16,981
  • 4
  • 79
  • 106
akivajgordon
  • 8,761
  • 1
  • 19
  • 27
  • You must then do this on all of the classes stubbed methods and cannot call `OCMVerifyAll(mock)`, right? Do you know is still the best approach for current versions of OCMock? (OCMockito seems to have better support in this area.) – Drux Feb 15 '15 at 20:22
  • I agree that I wish OCMock had better support ```OCMVerify(stub, callCount)```, but this works well. Great answer. – Daniel Wabyick Apr 16 '15 at 17:53
  • Similar idea: use the [OCMArg checkWithBlock:] and update the callCount from that block. But somehow this doesn't work as expected. The checkWithBlock is called 2 times for every method call. – JanR Dec 16 '16 at 11:29
4

If you need to check if a method is only called once, you can do it like this

[self.subject doSomething];
OCMVerify([self.mock method]);

OCMReject([self.mock method]);
[self.subject doSomething];
cornr
  • 653
  • 4
  • 20