I'm reading the OCMock reference and I'm confused about these two OCMArg methods invokeBlockWithArgs (section 2.6)
The mock object will invoke the block passed as an argument to the stubbed method. If the block takes arguments and invokeBlock is used, the default values for the argument types are used, e.g. zero for a numerical type. Using invokeBlockWithArgs: it is possible to specify which arguments to invoke the block with; non-object arguments must be wrapped in value objects and the expression must be wrapped in round brackets.
and checkWithBlock (section 4.3)
For checkWithSelector:onObject:, when the mock object receives someMethod:, it invokes aSelector on anObject. If the method takes an argument the mock will pass the argument that was passed to someMethod:. The method should return a boolean indicating whether the argument matched the expectation or not.
So with checkWithBlock we can call the passed block with whatever arguments we provide, and with invokeBlockWithArgs it seems possible to do the same too. So when should I use the first or the second method?
checkWithBlock- you provide a block that will be called to assert that a value passed to the stubbed method, which you exchanged with[OCMArg checkWithBlock:]meets your expectations.invokeBlockWithArgs- this can be used when stubbing block arguments, to invoke them with sample arguments. This is needed if you want to check the behavior of the block.Let's imagine that we have a simple
Networkingclient with just a single method :We also have some
ModelClassthat takes an instance of ourNetworkingas a dependency ininit, and looks something like this :We can then test the
getDatamethod like this in our test class :In the last example, if you used
checkWithBlockinstead ofinvokeBlockWithArgs, the completion block passed inModelClasswouldn't get called. Instead, the custom assertion block would be called (as we've seen in second test) and a pointer to the completion block would be passed as the value.You could of course cast this pointer to the block type, and invoke the block yourself with some arguments - but that's extra work that can be avoided thanks to
invokeBlockWithArgs.Note :
invokeBlockWithArgstakes avar_argslist of arguments that needs to be terminated withnilto indicate the end. We need to use[NSNull null]to indicate that we wantnilto be passed as a certain argument to our completion block - so in the example above our completion block will be called withexpectedDataasnewData, andnil(from[NSNull null]) asnewError.