31

假设一个方法签名,如下所示:

- (void)theMethod:(void(^)(BOOL completed))completionBlock;

我想模拟这个方法签名以确保调用该方法,并且只调用完成块。我从类似这篇文章的其他帖子中看到,我可以模拟方法调用并接受任何块,但不能运行该块。我也知道有一个我可以使用的 andDo 方法,但我不知道如何传递一个块并运行它。

有任何想法吗?

谢谢。

4

5 回答 5

34

您可以[[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。

于 2013-05-13T20:19:29.753 回答
17

编辑 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);
于 2013-05-14T07:40:11.507 回答
11

现在 OCMock 3.2 支持此功能。您可以使用[OCMArg invokeBlock]and[OCMArg invokeBlockWithArgs:...]调用作为参数传递给存根方法的块。

于 2015-10-05T09:58:48.900 回答
8

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 文档中阅读有关它的更多信息。

于 2015-12-23T16:56:24.883 回答
5

这是 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);
});
于 2016-09-23T07:37:09.333 回答