Returning CGRect from mocked method crashes
Asked Answered
C

2

14

I was just practising OCMock, The problem I am facing here is

I have one method named foo which returns CGRect, this method is called from another method callFoo.

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

My unit test for callFoo method is bellow.

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

When this test case runs,I am getting an unexpected crash when it reaches CGRect rect = [self foo];
I wanted to know why this crash is happening if we return CGRect from mocked method and how to resolve this crash.

Could any one please help to resolve this problem.

Thanks in advance.

P.S : This works fine if I replace CGRect with NSValue. As shown below

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

and in my test case,

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

update :
This looks like problem with the memory [but I am not sure, just a guess].

Mocked method will give me correct structure if I create a structure with 2 CGFloat variable, whereas it will crash if I create the structure with 2 double variable or 3 CGFloat variable.

Interesting :)

Constanceconstancia answered 15/5, 2013 at 7:28 Comment(3)
This seems to be a bug in OCMock. It ends up making foo point to a null implementation within the partial mock (you may have seen that if you call foo directly you can get the test to pass). An (admittedly not great) workaround would be to put foo in a different class and mock that.Symbiosis
I am not sure whether it is a bug in OCMock, but when I tried with custom struct which is similar to CGRect ie. struct contains two structs(struct1 & struct2) which contains two variables in it. But the result is same, it crashed. But if I the structs ie struct1 and struct2 contains only one variable in it then the test will passConstanceconstancia
This was a bug in OCMock, which has been fixed now: github.com/erikdoe/ocmock/pull/41 If you look at the comments on the pull request, you'll see why there were only problems with some (usually large) structs.Palpebrate
C
0

This seems to be a bug in OCMock. which is fixed now.

Constanceconstancia answered 30/9, 2013 at 10:49 Comment(0)
M
4

OCMOCK_VALUE is usually for primitives (BOOL, NSInteger, etc.) It seems that OCMOCK_VALUE doesn't work well with structs, according to the following links.

If you use the categories provided by the post OCMock Return a struct, you can do something like:

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

Alternatively, you can use OCMOCK_STRUCT from Using a struct with OCMock or 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];
 }
Macguiness answered 24/5, 2013 at 16:7 Comment(4)
I have tried CGRect rect = {0, 0, 0, 0}; NSValue *valRect = [NSValue valueWithBytes:&rect objCType:@encode(CGRect)]; [[[master expect] andReturnValue:valRect] foo]; but it crashed.Constanceconstancia
Did you try [[[master expect] andReturn:valRect] foo];?Macguiness
OCMOCK_VALUE works perfectly fine with structs. You can also stub methods that return CGRect using normal mocks. The problem is somehow related to the use of a partial mock. I see crashes in the scenario described here, too, but I still haven't figured out the exact reason.Palpebrate
codeforfun.wordpress.com/2009/02/07/ocmock-return-a-struct seems to be broken on Xcode11Consistory
C
0

This seems to be a bug in OCMock. which is fixed now.

Constanceconstancia answered 30/9, 2013 at 10:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.