繁体   English   中英

具有从测试方法调用的方法的类的OCMock

[英]OCMock of class with method called from the test method

我正在尝试测试实例化MFMailComposeViewController实例的方法。 被测试的方法调用MFMailComposeViewController几种方法,包括setSubject:

我想测试是否向setSubject发送了特定的NSString,在这种情况下为@“ Test Message”。
无论我在模拟存根中为期望的字符串指定什么内容,都不会失败。

在单元测试类中:

#import <OCMock/OCMock.h>

- (void)testEmail {
    TestClass *testInstance = [[TestClass alloc] init];

    id mock = [OCMockObject mockForClass:[MFMailComposeViewController class]];
    [[mock stub] setSubject:@"Test Message"];

    [testInstance testMethod];
}

在TestClass中:

- (void)testMethod {
    MFMailComposeViewController *mailComposeVC = [[MFMailComposeViewController alloc] init];
    [mailComposeVC setSubject:@"Bad Message"];
}

Test Suite 'Email_Tests' started at 2011-09-17 18:12:21 +0000
Test Case '-[Email_Tests testEmail]' started.
Test Case '-[Email_Tests testEmail]' passed (0.041 seconds).

测试应该失败了。

我正在iOS模拟器中对此进行测试,并在设备上获得相同的结果。

我究竟做错了什么? 有什么办法可以做到这一点?

您创建了一个模拟,但绝不将其传递给测试中的类,或者让该模拟进行验证。 您需要某种形式的依赖项注入来说:“而不是使用MFMailComposeViewController,请使用我给您的另一件事。”

这是一种方法。 在被测类中,不要直接分配MFMailComposeViewController,而是通过工厂方法来获取它,如下所示:

@interface TestClass : NSObject

- (void)testMethod;

// Factory methods
+ (id)mailComposeViewController;

@end

这是实现。 您正在泄漏,因此请注意factory方法将返回一个自动释放的对象。

- (void)testMethod {
    MFMailComposeViewController *mailComposeVC =
                                    [[self class] mailComposeViewController];
    [mailComposeVC setSubject:@"Bad Message"];
}

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

在测试方面,我们创建了一个覆盖工厂方法的测试子类,因此它提供了我们想要的一切:

@interface TestingTestClass : TestClass
@property(nonatomic, assign) id mockMailComposeViewController;
@end

@implementation TestingTestClass
@synthesize mockMailComposeViewController;

+ (id)mailComposeViewController {
    return mockMailComposeViewController;
}

@end

现在我们准备好进行测试了。 我做了一些不同的事情:

  • 分配测试子类而不是实际类(不要泄漏!)
  • 带着期望而不只是存根设置模拟
  • 将模拟注入到测试子类中
  • 最后验证模拟

这是测试:

- (void) testEmail {
    TestClass *testInstance = [[[TestClass alloc] init] autorelease];

    id mock = [OCMockObject mockForClass:[MFMailComposeViewController class]];
    [[mock expect] setSubject:@"Test Message"];
    [testInstance setMockMailComposeViewController:mock];

    [testInstance testMethod];

    [mock verify];
}

为了完整起见,我们需要一个最终测试,这是为了确保实际类中的工厂方法返回我们期望的结果:

- (void)testMailComposerViewControllerShouldBeCorrectType {
    STAssertTrue([[TestClass mailComposeViewController]
                 isKindOfClass:[MFMailComposeViewController class]], nil);
}

乔恩·里德(Jon Reid)的方法是一种合理的方法,尽管将mailComposeViewController类方法似乎使它变得复杂。 在测试代​​码中将其子类化意味着您将始终在测试时获得模拟版本,而这可能并不是您想要的。 我将其作为实例方法。 然后,您可以在测试时使用部分模拟覆盖它:

-(void) testEmail {
    TestClass *testInstance = [[[TestClass alloc] init] autorelease];

    id mock = [OCMockObject mockForClass:[MFMailComposeViewController class]];
    [[mock expect] setSubject:@"Test Message"];
    id mockInstance = [OCMockObject partialMockForObject:testInstance];
    [[[mockInstance stub] andReturn:mock] mailComposeViewController];

    [testInstance testMethod];

    [mock verify];
}

如果将其保留为类方法,则可以考虑使其成为静态全局变量,并提供一种覆盖它的方法:

static MFMailComposeViewController *mailComposeViewController = nil;

-(id)mailComposeViewController {
    if (!mailComposeViewController) {
        mailComposeViewController = [[MFMailComposeViewController alloc] init];
    }
    return mailComposeViewController;
}

-(void)setMailComposeViewController:(MFMailComposeViewController *)controller {
    mailComposeViewController = controller;
}

然后,您的测试将类似于乔恩的示例:

-(void)testEmail {
    TestClass *testInstance = [[[TestClass alloc] init] autorelease];

    id mock = [OCMockObject mockForClass:[MFMailComposeViewController class]];
    [[mock expect] setSubject:@"Test Message"];
    [testInstance setMailComposeViewController:mock];

    [testInstance testMethod];

    [mock verify];

    // clean up
    [testInstance setMailComposeViewController:nil];
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM