Problem with property invoked from partial mock

Discussion of the OCMock framework. If you have patches we would prefer you to send them to the mailing list, but attaching them to a topic is possible, too.

Problem with property invoked from partial mock

Postby tron_thomas » 23 Apr 2012, 05:58

This error:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'OCMockObject[Actor]: expected method was not invoked: perform'

Will result when executing the following code:

Code: Select all
#import <Foundation/Foundation.h>
#import <OCMock/OCMock.h>

@interface Actor : NSObject

- (void)perform;

@end

@implementation Actor

- (void)perform
{
   
}

@end

@interface Director : NSObject

@property (nonatomic, copy) Actor* actor;

- (void)direct;

@end

@implementation Director

@synthesize actor;

- (id)init
{
   self = [super init];
   if (self) {
      actor = [[Actor alloc] init];
   }
   
   return self;
}

- (void)direct
{
   [actor perform];
//   Actor* theActor = self.actor;
//   [theActor perform];
}

@end

int main(int argc, const char * argv[])
{

   @autoreleasepool {
      Director* director = [[Director alloc] init];
      
      id directorMock = [OCMockObject partialMockForObject:director];
      id actor = [OCMockObject mockForClass:[Actor class]];
      
      [[[directorMock stub] andReturn:actor] actor];
      
      [[actor expect] perform];
      
      [director direct];
      
      [actor verify];
   }
    return 0;
}


If someone comments out the call to [actor perform] in the direct method and un-comments the lines that follow it, the program runs fine.

What is the reason that invoking the property directly is problematic and storing the property in a local variable works fine?
tron_thomas
 
Posts: 19
Joined: 04 Mar 2012, 02:14

Re: Problem with property invoked from partial mock

Postby erik » 26 Apr 2012, 16:39

When you write "[actor perform];" the code sends the perform message to the object that is referenced by the actor instance variable. This is the object that's instantiated in the init method. The partial mock does not and cannot get involved here.

When you effectively do "[self.actor perform]" the perform message is send to the object that is returned by the actor method. This is the one overwritten by the partial mock. So, in this case perform is send to the actor mock, which is what you want, I guess.
erik
 
Posts: 90
Joined: 10 Oct 2009, 15:22
Location: Hamburg, Germany

Re: Problem with property invoked from partial mock

Postby tron_thomas » 27 Apr 2012, 04:00

I was thking that [actor perform] was equivalent to [self.actor perform]. I'm used to C++ where member = 3 is equivalent to this->member = 3. I also did not realize that synthesizing actually created an object with the property name. I was thinking the underlying variable for the property with have some internal, decorated name like __actor.
I guess I will have to remember to qualify a property call with the self variable.
tron_thomas
 
Posts: 19
Joined: 04 Mar 2012, 02:14


Return to OCMock