Can OCMock run a block parameter?

前端 未结 5 1831
予麋鹿
予麋鹿 2020-12-29 22:12

Assume a method signature such as the following:

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

I would like to mock this meth

相关标签:
5条回答
  • 2020-12-29 22:18

    EDIT 2: Use https://stackoverflow.com/a/32945785/637641 instead.

    Using andDo: is perfectly fine, but personally I prefer [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];
    

    You can use also [mock stub] but I prefer to verify that theMethod is called.

    EDIT 1

    OCMock 3 version:

    OCMExpect([mock theMethod:[OCMArg checkWithBlock:^BOOL(void (^passedBlock)(BOOL))
    {
        // call the block...
        return YES;
    }]]);
    
    // Code to test
    
    OCMVerify(mock);
    
    0 讨论(0)
  • 2020-12-29 22:28

    This is now supported in OCMock 3.2. You can use [OCMArg invokeBlock] and [OCMArg invokeBlockWithArgs:...] to invoke the block passed as an argument to a stubbed method.

    0 讨论(0)
  • 2020-12-29 22:28

    This is Sven's answer updated for OCMock 3.

    OCMStub([myMock myMethodWithMyBlock:[OCMArg any]]).andDo(^(NSInvocation *invocation) {
        void (^passedBlock)(BOOL myFirstArgument, NSError *mySecondArgument);
        [invocation getArgument: &passedBlock atIndex: 2];
        passedBlock(YES, nil);
    });
    
    0 讨论(0)
  • 2020-12-29 22:33

    Using andDo: blocks is sometimes required but for most cases you can use [OCMArg invokeBlock] or [OCMArg invokeBlockWithArgs:].

    In your example you can do the following
    If you don't care about the arguments:

    // Call block with default arguments.
    OCMStub([mock theMethod:[OCMArg invokeBlock]];
    

    If you want to send specific arguments:

    // Call block with YES.
    OCMStub([mock theMethod:([OCMArg invokeBlockWithArgs:@YES, nil])];
    

    Note the nil termination since you can pass multiple arguments to this method. In addition the entire expression must be wrapped in parentheses.

    You can read more about it in the OCMock documentation.

    0 讨论(0)
  • 2020-12-29 22:37

    You can use [[mock stub] andDo:] like this to pass another block that gets called when your mocked method is called:

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

    The block gets a NSInvocation instance from which you can query all the used arguments. Note that the first argument is at index 2 since you have self and _cmd at the indices 0 and 1.

    0 讨论(0)
提交回复
热议问题