Как проверить, что частичная имитация имеет базовый метод, вызванный с аргументами, используя ocmock? - PullRequest
1 голос
/ 20 марта 2012

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

- (void)getPlacesForLocation:(Location *)location WithKeyword:(NSString *)keyword
{
    NSString *gps = [NSString stringWithFormat:@"?location=%@,%@", location.lat, location.lng];
    NSURL *url = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%@%@", self.baseurl, gps]];
    [super makeGetRequestWithURL:url];
}

Вот определение базового метода

@implementation WebService
@synthesize responseData = _responseData;

- (id)init
{
    if (self == [super init])
    {
        self.responseData = [NSMutableData new];        
    }

    return self;
}

- (void)makeGetRequestWithURL:(NSURL *)url
{
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
    request.HTTPMethod = @"GET";

    [[NSURLConnection alloc] initWithRequest:request delegate:self];
}

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

- (void)testGetRequestMadeWithUrl
{
    self.sut = [[SomeWebService alloc] init];
    Location *location = [[Location alloc] initWithLatitude:@"-33.8670522" AndLongitude:@"151.1957362"];
    NSURL *url = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%@%@", self.sut.baseurl, @"?location=-33.8670522,151.1957362"]];
    id mockWebService = [OCMockObject partialMockForObject: self.sut];
    [[mockWebService expect] makeGetRequestWithURL:url];
    [self.sut getPlacesForLocation:location WithKeyword:@"foo"];
    [mockWebService verify];
}

Тем не менее, когда я запускаю этот тест, у меня возникает ошибка со следующей ошибкой:

ожидаемый метод не был вызван: makeGetRequestWithURL: https: //...

Я могу сказать, что этот метод не является фиктивным, потому что, если я помещаю NSLog в базовый метод, он появляется, когда я запускаю тест ocunit (ясно, что он работает, просто не дразня его, как хотелось бы).

Как я могу изменить свой тест / рефакторинг моего кода реализации, чтобы получить утверждение, которое я ищу?

1 Ответ

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

Это интересный случай. Я предполагаю, что если вы замените «super» на «self», то все будет работать так, как ожидалось, т.е.

- (void)getPlacesForLocation:(Location *)location WithKeyword:(NSString *)keyword
{
    NSString *gps = [NSString stringWithFormat:@"?location=%@,%@", location.lat, location.lng];
    NSURL *url = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%@%@", self.baseurl, gps]];
    [self makeGetRequestWithURL:url];
}

Проблема в том, что частичные имитации реализуются путем создания подклассов на лету. При использовании «super» поиск метода начинается с родительского класса, базового класса в вашем случае, что означает, что среда выполнения никогда не увидит метод, реализованный в подклассе, созданный частичным макетом.

Другой ответ на ваш вопрос - изменить дизайн. Вместо использования иерархии классов используйте два класса. Один класс будет отвечать за создание URL, другой - за выполнение запросов. Тогда вам не понадобятся частичные макеты, потому что вы можете просто заменить создатель запросов. См. Принцип единой ответственности [1] и Состав по наследованию [2].

[1] http://en.wikipedia.org/wiki/Single_responsibility_principle

[2] http://en.wikipedia.org/wiki/Composition_over_inheritance

...