首页 文章

单元测试ViewController的生命周期

提问于
浏览
7

我正在为我的ViewControllers编写单元测试 . viewDidAppear:,viewWillAppear:等方法的最佳实践是什么?

我正在使用调用viewDidLoad的[vc view] . 但除了viewDidLoad之外,我应该如何对其他生命周期方法进行单元测试 . 对它们进行单元测试是否常见?直接调用它们是否有意义?喜欢:

[vc viewWillAppear:NO];
[vc viewDidAppear:NO];

谢谢

2 回答

  • 4

    有很多开发人员要么避免也不相信你可以测试UIViewControllers . Apples poor testing doco也没有帮助 .

    UIViewControllers是可以测试的,您可以采用多种方法 .

    首先,正如任何人都会告诉你的那样,尝试将业务逻辑保留在视图控制器之外 . 尝试使它只是加载视图,尽可能少 . 从MVC架构转变为其他可能有助于此 . 根据您正在构建的内容,您可能还需要考虑使用自定义UIView类来提供帮助 .

    纯单元/逻辑测试

    我正在处理Apple称之为'Logic test'的内容,即没有分配可执行文件的测试目标 . 你仍然可以测试很多 . 包含简单视图处理代码的方法可以通过手动设置视图或使用测试代码手动加载xib文件等进行测试 . 模拟框架(如OCMock)也非常有用 .

    通常,在这些类型的测试中,您最终需要手动执行各种生命周期方法来执行您要测试的代码 . 例如,如果您要测试 viewDidLoad 方法:

    id mockView = OCMClassMock([UIView class]);
    // Setup mock expectations.
    myViewController.view = mockView;
    [myViewController viewDidLoad];
    

    应用程序测试

    如果您使用的是设置应用程序的测试目标,那么您实际上可以使用单元测试进行一些测试,而无需尝试导航应用程序 . 这有点像作弊,但我发现它有时非常有用 .

    UIView *myView = // ... load the view manually or simply [[UIView alloc] initWithFrame:CGRectMake(0,0,100,100)]  
    myViewController.view = myView;
    [[UIApplication sharedApplication].keyWindow addSubview:myView];
    

    如果采用这种方法,请务必删除拆解中的视图 . 这样做的好处是可以自动为您调用在屏幕上获取视图的所有生命周期方法 .

    大多数情况下,我发现这对于与视图控制器和与作为较大屏幕布局的一部分的视图相关的自定义视图相关的测试内容非常有用 . 顶级视图控制器并非如此 .

    UI测试

    最后,Apple提供了新的UI测试框架 . 我曾经使用过像Frank和_1460690这样的第三方Ruby框架 . 事实证明,Apples UI Testing实际上非常好,与这些工具相当 .

    它的技巧是使用它来构建一个有意义的方法库,并帮助描述(使用DSL)应用程序的各个方面 .

    这种方法的缺点是您不能只加载要测试的视图 . 您必须实际运行该应用程序并导航到它 . 另一个主要缺点是它非常基于您的应用程序的基于外部可访问性的视图 . 几乎不可能进入内部,因此测试是基于屏幕行为的应用而不是内部类 .

    到目前为止,我还没有探讨混合这种形式的测试和手动将视图加载到窗口的想法,但我不明白为什么这样做不起作用 .

  • 3

    你刚刚感受到iOS ViewControllers的一大亮点: they suck at testability .

    MVC的另一个大问题是它不鼓励开发人员编写单元测试 . 由于视图控制器将视图操作逻辑与业务逻辑混合在一起,因此为了单元测试而将这些组件分离出来是一项艰巨的任务 . 很多人都不赞成的任务......只是没有测试任何东西 .

    source

    不要测试UIKit!你应该测试自己的逻辑 . 将逻辑放入VC中会使测试变得非常困难 . 尝试把它放在其他地方并单独测试它 . 答案是:你应该通过调用UIKit方法来避免测试 - 尤其是这些方法不能直接调用!

    如果从ViewController中获取所有逻辑,它将真正成为一个视图:一个在屏幕上显示内容的哑类 . 那里应该没有什么可以测试的 .

    也许您应该考虑使用MVVM / MVP / VIPER . 请阅读提供的链接,它将解释所有 .

相关问题