Может ли OCMock запустить параметр блока?
Предположим, что существует сигнатура метода:
- (void)theMethod:(void(^)(BOOL completed))completionBlock;
Я хотел бы высмеять эту подпись метода, чтобы гарантировать, что метод вызывается, и просто вызвать блок завершения. Я вижу из других сообщений, таких как этот, что я могу высмеять вызов метода и принять любой блок, но не запустить блок. Я также знаю, что есть метод andDo, который я мог бы использовать, но я не могу понять, как передать блок и запустить его.
Любые идеи?
Спасибо.
Ответы
Ответ 1
Вы можете использовать [[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, так как у вас есть self и _cmd по индексам 0 и 1.
Ответ 2
ИЗМЕНИТЬ 2:
Вместо этого используйте fooobar.com/questions/201519/....
Использование 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], но я предпочитаю проверять, что вызывается метод.
ИЗМЕНИТЬ 1
Версия OCMock 3:
OCMExpect([mock theMethod:[OCMArg checkWithBlock:^BOOL(void (^passedBlock)(BOOL))
{
// call the block...
return YES;
}]]);
// Code to test
OCMVerify(mock);
Ответ 3
Теперь это поддерживается в OCMock 3.2. Вы можете использовать [OCMArg invokeBlock]
и [OCMArg invokeBlockWithArgs:...]
для вызова блока, переданного в качестве аргумента, к обрезаемому методу.
Ответ 4
Иногда требуется использование блоков 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.
Ответ 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);
});