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

时间:2011-11-16 08:53:43

标签: objective-c ios unit-testing mocking

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

[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;
                   }
               }];

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

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

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

也可以使用委托来替换块,但我绝对更喜欢在这里使用块。

2 个答案:

答案 0 :(得分: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);

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

在标题中:

typedef void(^AuthenticationHandlerBlock)(UserLoginResponse);
-(AuthenticationHandlerBlock)authenticationHandler;

在您的实施中:

-(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;
       }
    }
}

在你的测试中:

AuthenticationHandlerBlock block = [user authenticationHandler];
block(UserLoginResponseSuccess);
// verify success outcome
block(UserLoginResponseFailureAuthentication);
// verify failure outcome
block(UserLoginResponseFailureB);
// verify failure B outcome

答案 1 :(得分:2)

对于那些在回答这个问题2年多后回答这个问题的读者,Kiwi现在支持嘲笑v2.2中的这些类方法。由于OP使用的是Kiwi,我觉得它比接受的答案要清晰得多......

请查看https://github.com/allending/Kiwi/issues/200了解详情。