OCMock可以运行块参数吗?

时间:2013-05-13 20:02:41

标签: ios unit-testing ocmock

假设方法签名如下:

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

我想模拟此方法签名以确保调用该方法,并只调用完成块。我从this one等其他帖子中看到,我可以模拟方法调用并接受任何块,但不能运行块。我也知道有一种我可以使用的doDo方法,但我无法弄清楚如何传递一个块并运行它。

有什么想法吗?

感谢。

5 个答案:

答案 0 :(得分:32)

您可以像这样使用[[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。

答案 1 :(得分: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);

答案 2 :(得分:11)

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

答案 3 :(得分:7)

有时需要使用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 documentation中了解更多相关信息。

答案 4 :(得分:2)

这是针对OCMock 3更新的Sven的答案。

OCMStub([myMock myMethodWithMyBlock:[OCMArg any]]).andDo(^(NSInvocation *invocation) {
    void (^passedBlock)(BOOL myFirstArgument, NSError *mySecondArgument);
    [invocation getArgument: &passedBlock atIndex: 2];
    passedBlock(YES, nil);
});