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 :)

Prasad Devadiga
  • 2,573
  • 20
  • 43
  • 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. – Ben Flynn May 16 '13 at 17:29
  • 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 pass – Prasad Devadiga May 21 '13 at 12:34
  • 1
    This was a bug in OCMock, which has been fixed now: https://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. – Erik Doernenburg Aug 09 '13 at 13:09

2 Answers2

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];
 }
Community
  • 1
  • 1
catcyborg
  • 344
  • 1
  • 10
  • 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. – Prasad Devadiga May 27 '13 at 04:44
  • Did you try `[[[master expect] andReturn:valRect] foo];`? – catcyborg May 28 '13 at 10:42
  • 1
    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. – Erik Doernenburg Jul 29 '13 at 22:16
  • http://codeforfun.wordpress.com/2009/02/07/ocmock-return-a-struct/ seems to be broken on Xcode11 – harshith__ Sep 12 '19 at 15:05
0

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

Prasad Devadiga
  • 2,573
  • 20
  • 43