如何模拟块的结果作为方法参数?

tim*_*tim 2 unit-testing mocking objective-c ios

我有一个方法在模型中触发异步请求并传递一个处理响应的块:

[user loginWithEmail:self.eMailTextField.text
         andPassword:self.passwordTextField.text
               block:^(UserLoginResponse response) {
                   switch (response) {
                       case UserLoginResponseSuccess:
                       {
                           // hooray
                           break;
                       }
                       case UserLoginResponseFailureAuthentication:
                           // bad credentials
                           break;
                       case UserLoginResponseFailureB:
                           // failure reason b
                           break;
                       default:
                           // unknown error
                           break;
                   }
               }];
Run Code Online (Sandbox Code Playgroud)

被调用的方法为请求设置一些参数,并使用AFNetworking启动它.

现在我想编写一个单元测试来确保调用类对每个可能的UserLoginResponse做出正确的反应.我正在使用Kiwi进行测试,但我认为这更像是一个普遍的问题......

我如何模拟从用户对象传递给块的参数?我能想到的唯一方法是模拟底层请求并返回我期望的测试状态代码.有没有更好的办法?

也可以使用委托来替换块,但我肯定更喜欢在这里使用块.

Chr*_*lay 7

看来你想在这里验证有两个不同的东西:1)用户对象传递对块的实际响应,以及2)块适当地处理各种响应代码.

对于#1,似乎正确的方法是模拟请求(该示例使用OCMockExpecta语法):

[[[request expect] andReturn:UserLoginResponseSuccess] authenticate];

__block UserLoginResponse actual;

[user loginWithEmail:nil
         andPassword:nil
               block:^(UserLoginResponse expected) {
                   actual = expected;
               }];

expect(actual).toEqual(UserLoginResponseSuccess);
Run Code Online (Sandbox Code Playgroud)

对于#2,我将创建一个返回要验证的块的方法.然后你可以直接测试它而不需要所有其他依赖项:

在你的标题中:

typedef void(^AuthenticationHandlerBlock)(UserLoginResponse);
-(AuthenticationHandlerBlock)authenticationHandler;
Run Code Online (Sandbox Code Playgroud)

在您的实施中:

-(AuthenticationHandlerBlock)authenticationHandler {
    return ^(UserLoginResponse response) {
       switch (response) {
           case UserLoginResponseSuccess:
           {
               // hooray
               break;
           }
           case UserLoginResponseFailureAuthentication:
               // bad credentials
               break;
           case UserLoginResponseFailureB:
               // failure reason b
               break;
           default:
               // unknown error
               break;
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

在你的测试中:

AuthenticationHandlerBlock block = [user authenticationHandler];
block(UserLoginResponseSuccess);
// verify success outcome
block(UserLoginResponseFailureAuthentication);
// verify failure outcome
block(UserLoginResponseFailureB);
// verify failure B outcome
Run Code Online (Sandbox Code Playgroud)