OCMock - Unexpected Method Invoked although expected

邮差的信 提交于 2019-12-24 10:52:55

问题


Here is the tested code:

if ([MFMailComposeViewController canSendMail]) {
        MFMailComposeViewController *mailComposeController = [[MFMailComposeViewController alloc] init];
        [mailComposeController setSubject:nil];
        [mailComposeController setToRecipients:@[Text_Email_Me_Email]];
        [mailComposeController setMailComposeDelegate:self];
        [self.frontViewController presentViewController:mailComposeController
                                               animated:YES
                                             completion:nil];

    }

Here is the testing code:

 id mailComposerMock = [OCMockObject mockForClass:[MFMailComposeViewController class]];
[[[mailComposerMock stub] andReturnValue:@YES] canSendMail];
[[[mailComposerMock stub] andReturn:mailComposerMock] alloc];
(void)[[[mailComposerMock stub] andReturn:mailComposerMock] init];
[[[mailComposerMock expect] andReturn:nil] setMailComposeDelegate:self.contactItemManager];
[[[mailComposerMock expect] andReturn:nil] setToRecipients:@[@"email@email.com"]];
[[[mailComposerMock expect] andReturn:nil] setSubject:nil];
[[[mailComposerMock expect] andReturn:self.frontViewController] presentingViewController];
[self.contactItemManager handleSelectionOfContentItemWithTitle:Text_Contact_Me_Email_Me];
[mailComposerMock verify];

The error states:

[theTestingClass testEmailMe] failed: OCMockObject[MFMailComposeViewController]: unexpected method invoked: setSubject:nil 

And as you can see, I am calling setSubject already.


回答1:


I haven't determined exactly why this is happening, but you can get around it if you build in some dependency injection:

- (void)handleSelectionOfContentItemWithTitle:(NSString *)title mailComposeViewController:(MFMailComposeViewController *)mailComposeViewController;

Additionally, avoid returning nil in void methods.

[[mailComposerMock expect] setSubject:nil];

If you were to pass your mock object into a method that could take the compose controller as an argument, your test should work.

Alternatively you could mock a custom factory method:

+ (MFMailComposeViewController*)mailComposeViewController
{
    return [[MFMailComposeViewController alloc] init];
}

Not quite an answer, but hopefully a helpful workaround. I avoid mocking alloc and init personally.




回答2:


I think that here:

(void)[[[mailComposerMock stub] andReturn:mailComposerMock] init];

should be passed mock from method partialMockForObject not mockForClass.

My proposition is that you should create second mock which is made by partialMockForObject

Finally:

id mailComposerMock = [OCMockObject mockForClass:[MFMailComposeViewController class]];
MFMailComposeViewController *mailComposer = [MFMailComposeViewController new];
id partialComposerMock = [OCMockObject partialMockForObject:mailComposer];
...
(void)[[[mailComposerMock stub] andReturn: partialComposerMock] init];

[[[partialComposerMock expect] andReturn:nil] setMailComposeDelegate:self.contactItemManager];
[[[partialComposerMock expect] andReturn:nil] setToRecipients:@[@"email@email.com"]];
[[[partialComposerMock expect] andReturn:nil] setSubject:nil];
[[[partialComposerMock expect] andReturn:self.frontViewController] presentingViewController];
...
[partialComposerMock verify];


来源:https://stackoverflow.com/questions/21968556/ocmock-unexpected-method-invoked-although-expected

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!