这是正在测试的方法:
- (void)loginWithUser:(NSString *)userName andPass:(NSString *)pass {
    NSDictionary *userPassD = @{@"user":userName,
                                @"pass":pass};
    [_loginCntrl loginWithUserPass:userPassD withSuccess:^(NSString *authToken){
        // save authToken to credential store
    } failure:^(NSString *errorMessage) {
        // alert user pass was wrong
    }];    
}
我要测试的是,在该成功块中,使用适当的方法调用了其他依赖项/OCMockObject _credStore。所以目前 loginCtrl 和 credStore 依赖项是 OCMockObjects,我可以存根/期望这些。
我会存根 loginController 在调用时以某种方式执行该块吗?我已经查看了一些关于使用 OCMock 存根块的问题,但我无法理解他们正在做什么以及它是否适合这种情况。
实际上,我想做的只是 OCMock 触发块([成功调用]??),以便代码 _credStore saveUserPass 完成并且可以在 _credStore 上进行验证。
我停下来的地方:
- (void)test_loginWithuserPass_succeeds_should_call_credStore_setAuthToken {
    NSDictionary *userPassD = @{@"user":@"mark",
                                @"pass":@"test"};
    id successBlock = ^ {
        // ??? isn't this done in the SUT?
    };
    [[[_loginController stub] andDo:successBlock] loginWithUserPass:userPassD withSuccess:OCMOCK_ANY failure:OCMOCK_ANY];
    [[_credentialStore expect] setAuthToken:@"passed back value from block"];
    [_docServiceSUT loginWithUser:@"mark" andPass:@"test"];
    [_credentialStore verify];
}
ETA:这是我基于下面 Ben 的示例的内容,但无法正常工作,获得 EXC_BAD_ACCESS 异常:
// OCUnit test method
- (void)test_loginWithUserPass_success_block_should_call_credentials_setAuthToken {
    void (^proxyBlock)(NSInvocation*) = ^(NSInvocation *invocation) {
        void(^successBlock)(NSString *authToken);
        [invocation getArgument:&successBlock atIndex:3]; // should be 3 because my block is the second param
        successBlock(@"myAuthToken");
    };
    [[[_loginController expect] andDo:proxyBlock] loginWithUserPass:OCMOCK_ANY withSuccess:OCMOCK_ANY failure:OCMOCK_ANY];
    [[_credentialStore expect] setAuthToken:@"myAuthToken"];
    [_docServiceSUT loginWithUser:@"mark" andPass:@"myPass"];
    [_loginController verify];
    [_credentialStore verify];
}
//method under test
- (void)loginWithUser:(NSString *)userName andPass:(NSString *)pass {
    NSDictionary *userPassD = @{@"user":userName,
                                @"pass":pass};
    void(^onSuccess)(NSString *) = ^(NSString *authToken){
        [SVProgressHUD dismiss];
        [_credentials setAuthToken:authToken];
        // Ask user to enter the 6 digit authenticator key
        [self askUserForAuthenticatorKey];
    };
    void(^onFailure)(NSString *) = ^(NSString *errorMessage) {
        [SVProgressHUD dismiss];
        [_alertSender sendAlertWithMessage:errorMessage andTitle:@"Login failed"];
    };
    [SVProgressHUD show];
    [_loginCntrl loginWithUserPass:userPassD withSuccess:onSuccess
      failure:onFailure];
}