Как заглушить возвращаемое значение в методе класса, используя ocmock - PullRequest
0 голосов
/ 26 марта 2012

Я пишу тест для проверки запуска служб определения местоположения при нажатии кнопки. Это требует очень простого оператора if, чтобы убедиться, что в телефоне доступны службы определения местоположения.

Рабочий тест сейчас выглядит так

- (void)testStartUpdatingLocationInvokedWhenLocationServicesAreEnabled
{
    [[[self.locationManager stub] andReturnValue:[NSNumber numberWithBool:true]] locationServicesEnabled];
    [[self.locationManager expect] startUpdatingLocation];
    [self.sut buttonClickToFindLocation:nil];
    [self.locationManager verify];
}

Теперь протестированная реализация выглядит следующим образом

- (IBAction)buttonClickToFindLocation:(id)sender
{
    if ([self.locationManager locationServicesEnabled])
    {
        [self.locationManager startUpdatingLocation];
    }
}

Все хорошо, кроме метода устарел в iOS 4.0 . Поэтому теперь мне нужно использовать метод класса [CLLocationManager locationServicesEnabled].

Проблема в том, что я не могу найти, поддерживает ли ocmock эту функцию и если нет, то как мне обойти эту проблему сейчас.

Ответы [ 4 ]

3 голосов
/ 26 марта 2012

хммм, вы можете использовать methodExchange.Просто убедитесь, что вы изменили метод обратно на оригинальный после того, как с ним покончено.Это кажется хакерским, но я не нашел лучшего решения.Я сделал что-то похожее для зачистки [дата NSD]

@implementation

static BOOL locationManagerExpectedResult;

- (void)testStartUpdatingLocationInvokedWhenLocationServicesAreEnabled
{
    locationManagerExpectedResult = YES;

    method_exchangeImplementations(
       class_getClassMethod([CLLocationManager class], @selector(locationServicesEnabled)) , 
       class_getClassMethod([self class], @selector(locationServicesEnabledMock))
    );

    [self.sut buttonClickToFindLocation:nil];
}

+ (BOOL)locationServicesEnabledMock
{
    return locationManagerExpectedResult;
}

@end

РЕДАКТИРОВАТЬ : Я думал, что вы проверяете, но кажется, что вы окурки.Обновленный код

2 голосов
/ 26 марта 2012

Самый простой подход - переопределить locationServicesEnabled в категории в вашем классе модульных тестов:

static BOOL locationServicesEnabled = NO;

@implementation CLLocationManager (UnitTests)

+(BOOL)locationServicesEnabled {
    return locationServicesEnabled;
}

@end

...

-(void)tearDown {
    // reset to default after each test
    locationServicesEnabled = NO;
    [super tearDown];
}

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

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

В тестируемом классе:

-(BOOL)locationServicesEnabled {
    return [CLLocationManager locationServicesEnabled];
}

В вашем тесте:

-(void)testSomeLocationThing {
    MyController *controller = [[MyController alloc] init];
    id mockController = [OCMockObject partialMockForObject:controller];
    BOOL trackingLocation = YES;
    [[[mockController stub] andReturnValue:OCMOCK_VALUE(trackingLocation)] locationServicesEnabled];

    // test your controller ...
}
1 голос
/ 26 марта 2012

Я не думаю, что это так.Единственный подход, который я могу придумать, состоит в том, чтобы использовать частичную имитацию, а затем использовать вызовы времени выполнения, чтобы быстро реализовать нужную вам реализацию.

Выполнимо, но сложно.

Более ориентированное на шаблоны решение может заключаться в том, чтобы извлечь проверку для служб определения местоположения, чтобы сидеть за протоколом.Затем вы можете просто использовать макет для реализации протокола во время тестирования, чтобы вернуть YES или NO, как вам требуется.Поскольку фактическая реализация ничего не даст, кроме возврата [CLLocationManager locationServicesEnabled], вы можете избежать проверки.

0 голосов
/ 22 января 2015

Это поддерживается OCMock:

[[[[mockLocationManagerClass stub] classMethod] andReturnValue:OCMOCK_VALUE(YES)] locationServicesEnabled];
...