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 验证部分模拟是不是具有使用 args 调用的基本方法?