Отложенная проверка OCMock / Работа с тайм-аутом в модульных тестах

Я тестирую вызовы реальных веб-сервисов с помощью OCMock.

Сейчас я делаю что-то вроде:

- (void)testWebservice
{
    id mydelegatemock = [OCMockObject mockForProtocol:@protocol(MySUTDelegate)];
    [[mydelegatemock expect] someMethod:[OCMArg any]];

    [SUT sutWithDelegate:mydelegatemock];

    // we need to wait for real result
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];

    [(OCMockObject*)mydelegatemock verify];
}

Он отлично работает, но подразумевает, что каждый такой тест будет занимать 2 секунды.

Есть ли способ установить тайм-аут, например. 2 секунды, и пусть вызов someMethod из mydelegatemock немедленно verify и завершить контрольный пример?


person fabb    schedule 05.09.2011    source источник


Ответы (3)


Я делаю это с помощью удобной служебной функции, которую нашел по этой ссылке:

#import <Foundation/Foundation.h>
#import <OCMock/OCMock.h>

@interface TestUtils : NSObject
+ (void)waitForVerifiedMock:(OCMockObject *)mock delay:(NSTimeInterval)delay;
@end

И реализация:

#import "TestUtils.h"
@implementation TestUtils

+ (void)waitForVerifiedMock:(OCMockObject *)inMock delay:(NSTimeInterval)inDelay
{
    NSTimeInterval i = 0;
    while (i < inDelay)
    {
        @try
        {
            [inMock verify];
            return;
        }
        @catch (NSException *e) {}
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
        i+=0.5;
    }
    [inMock verify];
}

@end

Это позволяет мне ждать до максимальной задержки (в секундах), не дожидаясь полной суммы каждый раз.

person Tim Dean    schedule 06.09.2011
comment
Возможно, возник здесь?... touchalicious.com /блог/2009/11/5/ - person Max MacLeod; 09.04.2012
comment
Спасибо Макс - это похоже на источник. Я обновил исходный ответ ссылкой на оригинал. - person Tim Dean; 09.04.2012

Я бы отделил функциональное тестирование ваших веб-сервисов (если вам это вообще нужно) от модульного тестирования вашего класса, который обрабатывает результат веб-сервиса.

Для модульного тестирования вы должны смоделировать вызов веб-службы, предоставив фиктивный результат. Затем ваш тест проверит, что для этого четко определенного результата ваш класс ведет себя соответствующим образом.

Если вы также хотите провести функциональное тестирование своего веб-сервиса (скажем, он возвращает определенный ответ на какой-то запрос), вам не нужно ничего имитировать — просто вызовите сервис и сделайте утверждения о результате.

Разделяя тесты, вы лучше контролируете выполнение тестов. Например, вы можете запускать быстро выполняющиеся модульные тесты каждый раз при изменении кода, а медленно выполняющиеся функциональные тесты — каждую ночь, на выделенном сервере или по мере необходимости. А когда тест выйдет из строя, вы узнаете, виноват ли ваш код или что-то не так с веб-службой.

person Christopher Pickslay    schedule 06.09.2011
comment
У меня уже есть готовые тесты с немедленным поддельным возвратом из веб-сервиса. Этот вопрос касался интеграционных тестов с реальным веб-сервисом. Я допускаю, что прикладную часть я мог бы оставить в стороне в тех, но это не меняет того факта, что нужно как-то дождаться результата. И: с готовыми результатами я не проверяю наличие задержки между запросом и результатом, как и в случае с готовыми результатами, делегат результата фактически вызывается до завершения вызова запроса. - person fabb; 06.09.2011

Вы также можете переключиться на GHUnit, как предлагает один из участников в ответе на этот связанный вопрос:

SenTestingKit в Xcode 4: асинхронное тестирование?

Вы можете найти GHUnit здесь

https://github.com/gabriel/gh-unit

person thgc    schedule 10.05.2012