Как смоделировать результат для блока в качестве параметра метода? - PullRequest
2 голосов
/ 16 ноября 2011

У меня есть метод, который запускает асинхронный запрос в модели и передает блок, который обрабатывает ответ:

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

7 голосов
/ 17 ноября 2011

Похоже, что есть две разные вещи, которые вы хотите проверить здесь: 1) пользовательский объект передает фактический ответ блоку, и 2) блок обрабатывает различные коды ответа соответствующим образом.

Для # 1похоже, что правильный подход - это смоделировать запрос (в примере используется синтаксис OCMock и Expecta ):

[[[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
2 голосов
/ 31 июля 2013

Для тех читателей, которые пришли к этому вопросу через 2 с лишним года после того, как на него был дан ответ, теперь Kiwi поддерживает насмешку над этими методами класса, начиная с версии 2.2.Поскольку ОП использовал Kiwi, я полагаю, это чертовски много чище, чем принятый ответ :)

Подробнее смотрите https://github.com/allending/Kiwi/issues/200.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...