【发布时间】:2015-01-16 18:08:53
【问题描述】:
我们正在尝试编写自定义单元测试来分别测试每个视图控制器。我知道有 UI 自动化、KIF 和其他解决方案,但是如果您看一下上面的代码,您会发现不使用它们应该可以做到。
所以,为了简单起见,假设有一个简单的视图控制器,它有两个公共方法“setFirstState”和“setSecondState”。我需要测试,当视图控制器完全实例化并显示在屏幕上(通过 viewDidLoad)时调用的“setFirstState”方法。这是演示视图控制器:
@interface MyViewController
- (void)setFirstState;
- (void)setSecondState;
@end
@implementation MyViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setFirstState];
}
@end
因此,用于测试 setFirstState 调用的单元测试可能如下所示(使用 XCTest 和 OCMock):
- (void)test_viewDidLoad_CallsMyMethod {
MyViewController *viewContoller = [[MyViewController alloc] init];
id mock = [OCMockObject partialMockForObject:viewContoller];
[[mock expect] showLogin];
[UIApplication sharedApplication].keyWindow.rootViewController = (MyViewController *)mock;
[mock verify];
}
有趣的代码行是将 mock(在 viewController 上)分配给 keyWindow 的 rootViewController。我们发现如果我们想要调用 viewDidLoad、viewWillAppear 方法,就需要这样做。否则他们不会被调用。但是,如果我们运行测试,那么模拟器会挂在这条线上。 Xcode 显示它正在运行并且仍然存在,但它并没有更进一步。
我们还尝试将 keyWindow 的 rootViewController 代码行替换为“[mock viewDidLoad]”,仅用于模拟和测试 viewDidLoad,但它也挂起。因此,看起来部分模拟破坏了出现视图控制器的内部流程。
如果我们将移除 mock 并将视图控制器直接分配给 keyWindow 的 rootViewController 那么它就可以工作并且我们可以测试所有其他的东西。但是,也许有人知道我们如何解决这个问题?
更新忘了提到我们使用 Xibs 而不是 Storyboard,因此我们系统中的每个组件都是松散耦合的。
【问题讨论】:
-
访问视图属性并调用viewDidLoad。只需在这些方法的实际测试中调用 viewWillAppear 等。
-
不,将keyWindow的rootViewController代码行替换为“UIView *view = [mock view];”没有帮助。它也挂起。
标签: ios objective-c xctest ocmock ui-testing