Возврат CGRect из имитируемого метода завершается сбоем

Я просто практиковался OCMock. Проблема, с которой я столкнулся, заключается в следующем.

У меня есть один метод с именем foo, который возвращает CGRect, этот метод вызывается из другого метода callFoo.

-(CGRect)foo {
    return CGRectMake(10, 10, 10, 10);
}
-(void)callFoo {
    CGRect rect = [self foo];
    NSLog(@"%@",NSStringFromCGRect(rect));
}

Ниже приведен мой модульный тест для метода callFoo.

- (void)test__callFoo__invokesWithMockingFoo
{
     ViewController *sut = [[ViewController alloc] init];
     id master = [OCMockObject partialMockForObject:sut];

     CGRect rect = CGRectMake(0, 0, 0, 0);
     [[[master expect] andReturnValue:OCMOCK_VALUE(rect)] foo];
     [sut callFoo];
     [master verify];
 }

Когда выполняется этот тестовый пример, я получаю неожиданный сбой, когда он достигает CGRect rect = [self foo];
Я хотел знать, почему этот сбой происходит, если мы возвращаем CGRect из mocked method, и как решить этот сбой.

Может ли кто-нибудь помочь решить эту проблему.

Заранее спасибо.

P.S. Это прекрасно работает, если я заменю CGRect на NSValue. As shown below

 -(NSValue *)foo {
      return [NSValue valueWithCGRect:CGRectMake(10, 10, 10, 10)];
  }
  -(void)callFoo {
      CGRect rect = [[self foo] CGRectValue];
      NSLog(@"%@",NSStringFromCGRect(rect));
  }

и в моем тестовом примере

 NSValue *rect = [NSValue valueWithCGRect:CGRectMake(0, 0, 0, 0)];
 [[[master expect] andReturn:rect] foo];

обновление:
Это похоже на проблему с памятью [но я не уверен, просто предположение].

Метод mocked даст мне правильную структуру, если я создам структуру с 2 переменными CGFloat, тогда как он выйдет из строя, если я создам структуру с 2 переменными double или 3 переменными CGFloat.

Интересно :)


person Prasad Devadiga    schedule 15.05.2013    source источник
comment
Кажется, это ошибка в OCMock. Это приводит к тому, что foo указывает на нулевую реализацию в частичном макете (вы, возможно, видели, что если вы вызываете foo напрямую, вы можете пройти тест). Обходной путь (по общему признанию, не лучший) состоял бы в том, чтобы поместить foo в другой класс и высмеять его.   -  person Ben Flynn    schedule 16.05.2013
comment
Я не уверен, является ли это ошибкой OCMock, но когда я попытался использовать пользовательскую структуру, похожую на CGRect, т.е. struct содержит две структуры (struct1 и struct2), которые содержат две переменные. Но результат тот же, он разбился. Но если в структурах, т.е. struct1 и struct2, содержится только одна переменная, тест пройдет   -  person Prasad Devadiga    schedule 21.05.2013
comment
Это была ошибка в OCMock, которая сейчас исправлена: github.com/erikdoe/ocmock/pull /41 Если вы посмотрите на комментарии к пулреквесту, вы поймете, почему проблемы были только с некоторыми (обычно большими) структурами.   -  person Erik Doernenburg    schedule 09.08.2013
comment
@ErikDoernenburg Спасибо за информацию.   -  person Prasad Devadiga    schedule 12.08.2013


Ответы (2)


OCMOCK_VALUE обычно используется для примитивов (BOOL, NSInteger и т. д.). Похоже, что OCMOCK_VALUE плохо работает со структурами, согласно следующим ссылкам.

Если вы используете категории, указанные в сообщении, OCMock возвращает структуру вы можете сделать что-то вроде:

- (void)test__callFoo__invokesWithMockingFoo {
     ViewController *sut = [[ViewController alloc] init];
     id master = [OCMockObject partialMockForObject:sut];

     CGRect rect = CGRectMake(0, 0, 0, 0);
     [[[master expect] andReturnStruct:&rect objCType:@encode(CGRect)] foo];
     [sut callFoo];
     [master verify];
 }

В качестве альтернативы вы можете использовать OCMOCK_STRUCT из Использование структуры с OCMock или Hamcrest

- (void)test__callFoo__invokesWithMockingFoo {
     ViewController *sut = [[ViewController alloc] init];
     id master = [OCMockObject partialMockForObject:sut];

     CGRect rect = CGRectMake(0, 0, 0, 0);
     [[[master expect] andReturn:OCMOCK_STRUCT(CGRect, rect)] foo];
     [sut callFoo];
     [master verify];
 }
person catcyborg    schedule 24.05.2013
comment
Я пробовал CGRect rect = {0, 0, 0, 0}; NSValue *valRect = [NSValue valueWithBytes:&rect objCType:@encode(CGRect)]; [[[master expect] andReturnValue:valRect] foo];, но это не помогло. - person Prasad Devadiga; 27.05.2013
comment
Вы пробовали [[[master expect] andReturn:valRect] foo];? - person catcyborg; 28.05.2013
comment
OCMOCK_VALUE отлично работает со структурами. Вы также можете заглушить методы, которые возвращают CGRect, используя обычные макеты. Проблема как-то связана с использованием частичного макета. Я вижу сбои и в описанном здесь сценарии, но до сих пор не выяснил точную причину. - person Erik Doernenburg; 30.07.2013
comment
codeforfun.wordpress.com/2009/02/07/ocmock -return-a-struct кажется неработающим в Xcode11 - person harshith7823; 12.09.2019

Похоже, это ошибка в OCMock. что сейчас исправлено.

person Prasad Devadiga    schedule 30.09.2013