使用 OCMock 检查 IBOutlet 连接

Posted

技术标签:

【中文标题】使用 OCMock 检查 IBOutlet 连接【英文标题】:Checking IBOutlet connection with OCMock 【发布时间】:2011-01-14 09:55:26 【问题描述】:

我想通过单元测试来验证我的控制器类中的所有IBoutlets 是否正确连接到了 NIB 文件中。我想用 OCMock 来做这件事——即使我知道我可以在加载 NIB 后简单地断言控制器变量不是nil。这更多的是对流程如何工作的一般理解 - 据我所知,这也应该有效。

NIB OnOffSwitchCell 的文件所有者为 OnOffSwitchCellController。 这是我的测试方法:

- (void) testIBOutletCellIsWiredToXib 
    id mockController = [OCMockObject mockForClass:[OnOffSwitchCellController class]];
    [[mockController expect] awakeAfterUsingCoder:OCMOCK_ANY];
    [[mockController expect] setValue:OCMOCK_ANY forKey:@"cell"];
    [[mockController expect] setValue:OCMOCK_ANY forKey:@"thelabel"];
    [[mockController expect] setValue:OCMOCK_ANY forKey:@"theswitch"];

    NSArray* nibContents = [guiBundle loadNibNamed:@"OnOffSwitchCell"
                                             owner:mockController
                                           options:nil];
    assertThat(nibContents, isNot(nil));
    assertThatInt([nibContents count], is(equalToInt(1)));
    assertThat([nibContents objectAtIndex:0], is(instanceOf([OnOffSwitchCell class])));

    [mockController verify];

guiBundle 存在并被验证为有效的 NSBundle 对象。

据我了解loadNibNamed:owner:options: 将反序列化NIB 中的对象,调用awakeAfterUsingCoder:,然后通过调用setValue:forKey: 为每个对象设置出口。

我又添加了三个断言,以确保加载的 NIB 实际上包含正确的对象 - 当我放入真实控制器的实例时,这些断言可以通过。但是当我使用如上所示的模拟时,它甚至没有走到这一步。相反,测试会因此崩溃:

测试用例“-[OnOffSwitchCellControllerTestCase testIBOutletCellIsWiredToXib]”已启动。 2011-01-14 10:48:35.364 GTMTest[67797:903] *** 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序, 原因:'OCMockObject [OnOffSwitchCellController]: 调用了意外的方法:awakeAfterUsingCoder: 预期:setValue:<0x4c718e0><0x4c71ce0><0x4c71ed0>

【参考方案1】:

你试过在主系统线程上运行它吗?你不能在主线程之外实例化 UIKit 类。不确定 GTM 是如何做到的,但是使用 GHUnit,您可以将以下内容放入您的测试用例类中:

- (BOOL)shouldRunOnMainThread 
    /* Tell GHUnit to run on a separate thread */
    return YES;

【讨论】:

不幸的是,没有什么不同。【参考方案2】:

你实际上不能在单元测试中做任何视觉上的事情。视图从未实际加载。此外,您不需要测试是否调用了 awakeAfterUsingCoder。那是苹果的东西。通常,您的单元测试必须只测试您的逻辑。您可以放心地假设 awakeAfterUsingCoder 是从 init 调用的,因为它是 Apple 的代码。你只需要确保你的方法被调用

【讨论】:

以上是关于使用 OCMock 检查 IBOutlet 连接的主要内容,如果未能解决你的问题,请参考以下文章

void 方法的 OCMock 测试

在 OCMock 的 andDo 中访问参数时出现 EXC_BAD_ACCESS

OCmock 和 MKReverseGeocoder

UIImageView 的 UIImage 为 nil

无法在 Interface Builder 中连接 IBOutlet

接口生成器、@IBOutlet 以及 Swift 中委托和数据源的协议