假设一个方法签名,如下所示:
- (void)theMethod:(void(^)(BOOL completed))completionBlock;
我想模拟这个方法签名以确保调用该方法,并且只调用完成块。我从类似这篇文章的其他帖子中看到,我可以模拟方法调用并接受任何块,但不能运行该块。我也知道有一个我可以使用的 andDo 方法,但我不知道如何传递一个块并运行它。
有任何想法吗?
谢谢。
假设一个方法签名,如下所示:
- (void)theMethod:(void(^)(BOOL completed))completionBlock;
我想模拟这个方法签名以确保调用该方法,并且只调用完成块。我从类似这篇文章的其他帖子中看到,我可以模拟方法调用并接受任何块,但不能运行该块。我也知道有一个我可以使用的 andDo 方法,但我不知道如何传递一个块并运行它。
有任何想法吗?
谢谢。
您可以[[mock stub] andDo:]
像这样使用来传递另一个在调用您的模拟方法时被调用的块:
void (^proxyBlock)(NSInvocation *) = ^(NSInvocation *invocation) {
void (^passedBlock)( BOOL );
[invocation getArgument: &passedBlock atIndex: 2];
};
[[[mock stub] andDo: proxyBlock] theMethod:[OCMArg any]];
该块获取一个NSInvocation
实例,您可以从中查询所有使用的参数。请注意,第一个参数位于索引 2 处,因为您在索引 0 和 1 处有 self 和 _cmd。
编辑 2:改用https://stackoverflow.com/a/32945785/637641。
使用andDo:
非常好,但我个人更喜欢[OCMArg checkWithBlock:]
.
[[mock expect] theMethod:[OCMArg checkWithBlock:^BOOL(id param)
{
void (^passedBlock)( BOOL ) = param;
// Normally I set some expectations here and then call the block.
return YES;
}]];
// Code to test
[mock verify];
您也可以使用 [mock stub],但我更喜欢验证是否调用了 theMethod。
编辑 1
OCMock 3 版本:
OCMExpect([mock theMethod:[OCMArg checkWithBlock:^BOOL(void (^passedBlock)(BOOL))
{
// call the block...
return YES;
}]]);
// Code to test
OCMVerify(mock);
现在 OCMock 3.2 支持此功能。您可以使用[OCMArg invokeBlock]
and[OCMArg invokeBlockWithArgs:...]
调用作为参数传递给存根方法的块。
andDo:
有时需要
使用块,但在大多数情况下,您可以使用[OCMArg invokeBlock]
或[OCMArg invokeBlockWithArgs:]
。
在您的示例中,如果您不关心参数,您可以执行以下操作:
// Call block with default arguments.
OCMStub([mock theMethod:[OCMArg invokeBlock]];
如果要发送特定参数:
// Call block with YES.
OCMStub([mock theMethod:([OCMArg invokeBlockWithArgs:@YES, nil])];
请注意nil
终止,因为您可以将多个参数传递给此方法。此外,整个表达式必须用括号括起来。
您可以在OCMock 文档中阅读有关它的更多信息。
这是 Sven 为 OCMock 3 更新的答案。
OCMStub([myMock myMethodWithMyBlock:[OCMArg any]]).andDo(^(NSInvocation *invocation) {
void (^passedBlock)(BOOL myFirstArgument, NSError *mySecondArgument);
[invocation getArgument: &passedBlock atIndex: 2];
passedBlock(YES, nil);
});