ios - how to mock a property of an object conforming to a protocol and mocked by OCMock? -


i'm following examples in test driven ios development , in 1 case there unit test ensures delegate gets 'dumbed down' version of error method. without going many details here relevant objects:

  • communicator: object responsible making network calls
  • manager: instructs communicator make calls , pushes result delegate.
  • delegate: manager delegate conforms stackoverflowmanagerdelegate protocol. gets results , processes it.

so test is:

@implementation questioncreationtests  {     @private     stackoverflowmanager *mgr; } - (void)testerrorreturnedtodelegateisnoterrornotifiedbycommunicator {     mockstackoverflowmanagerdelegate *delegate =     [[mockstackoverflowmanagerdelegate alloc] init];     mgr.delegate = delegate;     nserror *underlyingerror = [nserror errorwithdomain: @"test domain"                                                    code: 0 userinfo: nil];     [mgr searchingforquestionsfailedwitherror: underlyingerror];     xctassertfalse(underlyingerror == [delegate fetcherror],                   @"error should @ correct level of abstraction"); } 

this implementation of searchingforquestionsfailedwitherror in stackoverflowmanager, manager dumbs down original error returned communicator , sends dumbed down version delegate.

- (void)searchingforquestionsfailedwitherror:(nserror *)error {     nsdictionary *errorinfo = [nsdictionary dictionarywithobject: error                                                           forkey: nsunderlyingerrorkey];     nserror *reportableerror = [nserror                                 errorwithdomain: stackoverflowmanagersearchfailederror                                 code: stackoverflowmanagererrorquestionsearchcode                                 userinfo:errorinfo];     [delegate fetchingquestionsontopic: nil                        failedwitherror: reportableerror]; } 

the author suggests work.. have create mock object manager delegate so:

@interface mockstackoverflowmanagerdelegate : nsobject <stackoverflowmanagerdelegate> @property (strong) nserror *fetcherror;  @end  @implementation mockstackoverflowmanagerdelegate  @synthesize fetcherror;  - (void)fetchingquestionsontopic: (topic *)topic                  failedwitherror: (nserror *)error {     self.fetcherror = error; }  @end 

this declaration of stackoverflowmanagerdelegate:

@protocol stackoverflowmanagerdelegate <nsobject>     - (void)fetchingquestionsontopic: (topic *)topic                  failedwitherror: (nserror *)error {     @end 

question: i've been going on examples of book , trying use ocmock instead of manually made ones author doing.. (i thought lot less time consuming). has worked far.. i'm stuck here.. how fake property called fetcherror on delegate? have right now:

- (void)testerrorreturnedtodelegateisnoterrornotifiedbycommunicator {     id <stackoverflowmanagerdelegate> delegate =         [ocmockobject mockforprotocol:@protocol(stackoverflowmanagerdelegate)];     mgr.delegate = delegate;      nserror *underlyingerror = [nserror errorwithdomain: @"test domain"                                                    code: 0 userinfo: nil];      [mgr searchingforquestionsfailedwitherror: underlyingerror];      // compiler error here: no known instance method selector 'fetcherror'     xctassertfalse(underlyingerror == [mgr.delegate fetcherror], @"error "); } 

in guts of manager, manager calls fetchingquestionsontopic on delegate.. know can fake method using [[[delegate stub] andcall:@selector(differentmethod:) onobject:differentobject] fetchingquestionsontopic:[ocmarg any]] differentmethod whatever want do.. don't know result of differentmethod: don't know how store in mocked out property of delegate.


update: follow answer below.. here implementation of unit test ensures underlying error still made available delegate:

- (void)testerrorreturnedtodelegatedocumentsunderlyingerror {     mockstackoverflowmanagerdelegate *delegate =     [[mockstackoverflowmanagerdelegate alloc] init];     mgr.delegate = delegate;     nserror *underlyingerror = [nserror errorwithdomain: @"test domain"                                                    code: 0 userinfo: nil];     [mgr searchingforquestionsfailedwitherror: underlyingerror];     xctassertequal([[[delegate fetcherror] userinfo]                           objectforkey: nsunderlyingerrorkey], underlyingerror,                          @"the underlying error should available client code"); } 

and here ocmock version of it:

- (void)testerrorreturnedtodelegatedocumentsunderlyingerrorocmock {     id delegate =     [ocmockobject mockforprotocol:@protocol(stackoverflowmanagerdelegate)];     mgr.delegate = delegate;      nserror *underlyingerror = [nserror errorwithdomain: @"test domain"                                                    code: 0 userinfo: nil];      [[delegate expect] fetchingquestionsfailedwitherror:        [ocmarg checkwithblock:^bool(id param) {          return ([[param userinfo] objectforkey:nsunderlyingerrorkey] == underlyingerror);      }]];      [mgr searchingforquestionsfailedwitherror: underlyingerror];      [delegate verify];  } 

try this:

- (void)testerrorreturnedtodelegateisnoterrornotifiedbycommunicator {     id delegate =         [ocmockobject mockforprotocol:@protocol(stackoverflowmanagerdelegate)];     mgr.delegate = delegate;      nserror *underlyingerror = [nserror errorwithdomain: @"test domain"                                                    code: 0 userinfo: nil];      [[delegate expect] fetchingquestionsontopic:ocmock_any                                  failedwitherror:[ocmarg isnotequal:underlyingerror]];      [mgr searchingforquestionsfailedwitherror:underlyingerror];      [delegate verify]; } 

to test domain, code , userinfo of error reported manager (if remember it's test case in book - read long time ago) this:

    id <stackoverflowmanagerdelegate> delegate =         [ocmockobject mockforprotocol:@protocol(stackoverflowmanagerdelegate)];     mgr.delegate = delegate;      nserror *underlyingerror = [nserror errorwithdomain: @"test domain"                                                    code: 0 userinfo: nil];      nserror *expectederror = [nserror errorwithdomain:@"expected domain"                                                   code:0/* expected code here*/                                               userinfo:@{nsunderlyingerrorkey: underlyingerror}];     [[delegate expect] fetchingquestionsontopic:ocmock_any                                  failedwitherror:expectederror];      [mgr searchingforquestionsfailedwitherror: underlyingerror];      [delegate verify]; 

Comments

Popular posts from this blog

java.util.scanner - How to read and add only numbers to array from a text file -

rewrite - Trouble with Wordpress multiple custom querystrings -