2012-03-20 2 views
1

Я работаю с очень простой веб-службой, которая использует базовый класс для повторного использования некоторых часто используемых функций. Основной тестируемый метод просто создает URL-адрес, а затем использует этот метод super/base.Как проверить частичный макет имеет базовый метод, вызываемый с помощью args с использованием ocmock?

- (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]; 
} 

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

- (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: // ...

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

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

ответ

3

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

- (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]; 
} 

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

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

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

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

+0

Awesome! спасибо за быстрый ответ! Любая проблема со мной, использующая self вместо SUPER здесь? –

+0

Не могу придумать. На самом деле, скорее всего, вы все равно хотели. Что бы вы ожидали, если бы вы предоставили переопределение для makeGetRequestWithURL: в классе, который содержит метод getPlacesForLocation: WithKeyword:? Вероятно, вы ожидаете, что переопределение будет вызвано, верно? Используя супер, вы говорите, что не хотите, чтобы это произошло, и вы определенно хотите использовать impl из родительского класса. –

Смежные вопросы