Подтвердить что ты не робот

Может ли OCMock запустить параметр блока?

Предположим, что существует сигнатура метода:

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

Я хотел бы высмеять эту подпись метода, чтобы гарантировать, что метод вызывается, и просто вызвать блок завершения. Я вижу из других сообщений, таких как этот, что я могу высмеять вызов метода и принять любой блок, но не запустить блок. Я также знаю, что есть метод andDo, который я мог бы использовать, но я не могу понять, как передать блок и запустить его.

Любые идеи?

Спасибо.

4b9b3361

Ответ 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);
});