OCMock 验证失败

Posted

技术标签:

【中文标题】OCMock 验证失败【英文标题】:OCMock verify fails 【发布时间】:2016-03-11 05:37:42 【问题描述】:

我正在尝试 OCMock 来测试是否在 viewDidLoad 上调用了 fetchContactsOnLoad 方法。下面是VC代码。

- (void)viewDidLoad 
    [super viewDidLoad];
    NSLog(@"%s", __FUNCTION__);
    [self fetchContactsOnLoad];


-(void)fetchContactsOnLoad 
    NSLog(@"%s", __FUNCTION__);
    [self.output doSomething:[ContactListRequest new]];

还有下面的测试。

- (void)testFetchContactsOnLoadInvoked 
    id vcMock = OCMClassMock([ContactListViewController class]);
    [vcMock view];
    OCMVerify([vcMock fetchContactsOnLoad]);

当我运行测试时会调用该方法,因为我可以看到 NSLog 的打印输出但测试失败。 我在考试中遗漏了什么?谢谢

【问题讨论】:

【参考方案1】:

首先,让我劝阻您不要尝试测试是否调用了fetchContactsOnLoad。最好测试调用fetchContactsOnLoad结果发生。

话虽如此,让我们继续。你怎么能测试fetchContactsOnLoad被调用了?这被称为“部分模拟”,因为您只模拟对象的 part,但想要保留其他所有内容。 (同样,这通常是个坏主意。但它对于遗留代码来说很方便。)

我会使用遗留测试技术 Subclass 和 Override Method。在我的测试代码中,我会创建一个特殊的子类:

@interface TestableContactListViewController : ContactListViewController
@property (nonatomic, assign) NSUInteger fetchContactsOnLoadCount;
@end

@implementation TestableContactListViewController

- (void)fetchContactsOnLoad 
    self.fetchContactsOnLoadCount += 1;


@end

有了这个,测试将如下所示:

- (void)testLoadingView_ShouldInvokeFetchContactsOnLoad 
    TestableContactListViewController *sut = [[TestableContactListViewController alloc] init];

    [sut view];

    XCTAssertEquals(sut.fetchContactsOnLoadCount, 1);

注意:这不涉及任何模拟框架。我手工创建了一个部分模拟。在处理模拟(或部分模拟)时,我建议从手工开始。一旦它变得乏味,那么一个模拟框架会让你更快。但是你会用你获得的知识编写更好的测试。

【讨论】:

部分模拟完成了这项工作。我对部分模拟所涉及的风险感到好奇,并希望有一些例子。在等待有人回复我的帖子时,我确实创建并使用了自己的模拟对象,但它需要大量额外的代码和重复。除非我找到可以自动为我创建模拟的东西,否则我可以做额外的事情。创建我自己的模拟的另一个问题,大多数时候 Xcode 覆盖没有发现使用了一个方法(也许另一个问题要发布,但谷歌结果似乎很少见)。谢谢! 本身没有技术风险,但必须使用部分模拟通常是一种设计味道;即一个类做的太多了。通常最好将不需要模拟的行为与需要模拟的行为分开,然后将这两个部分放入不同的类中。在这种情况下,您可以使用普通的模拟。 OCMock 添加了部分模拟,主要是为了解决 Apple 在基础框架中的一些类的类设计。

以上是关于OCMock 验证失败的主要内容,如果未能解决你的问题,请参考以下文章

在 NSMutableAttributedString 上模拟“initWithAttributedString”的 OCMock 失败

OCMock - 验证方法调用的顺序。还有其他方法吗?

如何使用 ocmock 验证部分模拟是不是具有使用 args 调用的基本方法?

如何使用OCMock验证在Objective C中不调用异步方法?

Ssh密码验证失败

为啥我的SSL证书验证失败