OCMock - 尽管预期会调用意外的方法

时间:2014-02-23 13:01:48

标签: objective-c unit-testing ocmock

以下是经过测试的代码:

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

    }

以下是测试代码:

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

错误说明:

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

正如你所看到的,我已经调用了setSubject。

2 个答案:

答案 0 :(得分:1)

我还没确定为什么会发生这种情况,但如果你构建了一些依赖注入,你可以绕过它:

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

此外,避免在void方法中返回nil

[[mailComposerMock expect] setSubject:nil];

如果你要将模拟对象传递给一个可以将compose控制器作为参数的方法,那么你的测试应该可行。

或者,您可以模拟自定义工厂方法:

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

不是一个答案,但希望是一个有用的解决方法。我个人避免嘲笑allocinit

答案 1 :(得分:-1)

我想在这里:

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

应该从方法partialMockForObject而不是mockForClass传递模拟。

我的主张是你应该创建第二个模拟,它由partialMockForObject

创建

最后:

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