web-dev-qa-db-ja.com

OCMockはブロックパラメーターを実行できますか?

次のようなメソッドシグネチャを想定します。

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

このメソッドシグネチャをモックして、メソッドが呼び出されることを確認し、完了ブロックを呼び出すだけです。 this one のような他の投稿から、メソッド呼び出しをモックして任意のブロックを受け入れることができますが、ブロックを実行できないことがわかります。また、使用できる可能性のあるandDoメソッドがあることも知っていますが、ブロックを渡して実行する方法がわかりません。

何か案は?

ありがとう。

29
Mike

このように[[mock stub] andDo:]を使用して、モックされたメソッドが呼び出されたときに呼び出される別のブロックを渡すことができます。

void (^proxyBlock)(NSInvocation *) = ^(NSInvocation *invocation) {
     void (^passedBlock)( BOOL );
     [invocation getArgument: &passedBlock atIndex: 2];
};
[[[mock stub] andDo: proxyBlock] theMethod:[OCMArg any]];

ブロックはNSInvocationインスタンスを取得し、そこから使用されているすべての引数をクエリできます。インデックス0と1にselfと_cmdがあるため、最初の引数はインデックス2にあることに注意してください。

32
Sven

編集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];

[モックスタブ]も使用できますが、私はtheMethodが呼び出されていることを確認することを好みます。

編集1

OCMock 3バージョン:

OCMExpect([mock theMethod:[OCMArg checkWithBlock:^BOOL(void (^passedBlock)(BOOL))
{
    // call the block...
    return YES;
}]]);

// Code to test

OCMVerify(mock);
17
e1985

これはOCMock 3.2でサポートされるようになりました。 [OCMArg invokeBlock][OCMArg invokeBlockWithArgs:...]を使用して、スタブメソッドに引数として渡されたブロックを呼び出すことができます。

11

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のドキュメント を参照してください。

7
Barak Yoresh

これは、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);
});
3
balkoth