2011-11-16 30 views
2

我有触发模型中的异步请求,并将该处理的响应的块的方法:如何模拟块的结果作为方法参数?

[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进行测试,但我认为这是一个更普遍的问题...

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

它也可以通过使用委托来替换块,但我肯定会更喜欢在这里使用块。

回答

7

看起来好像你想在这里验证2个不同的东西: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 
+0

谢谢,这真的帮了很多!我已经把' - (AuthenticationHandlerBlock)authenticationHandler;'放在我的ViewController中调用用户登录。唯一的缺点是我有一个新的公开方法。 原来的方法现在只是调用处理响应的'AuthenticationHandlerBlock'。 – tim

+1

如果您不希望它公开,则不必将其放在标题中。您可以在.m文件顶部的类别中声明它。您只需要将该类别复制到您的测试课程中,以避免警告。 –

2

对于那些读者在回答2年后才提出这个问题,现在猕猴桃支持嘲笑这些从v2.2开始的各种类方法。由于OP使用猕猴桃,我认为这是一个比接受的答案干净得多:)

看看https://github.com/allending/Kiwi/issues/200的细节。

相关问题