如何对`viewDidLoad()`进行单元测试

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何对`viewDidLoad()`进行单元测试相关的知识,希望对你有一定的参考价值。

ios上进行单元测试UIViewController.viewDidLoad()方法时,每个人最喜欢注入依赖关系的方式是什么?

鉴于我的实施是:

class MyViewController: UIViewController {

    var service: Service = Service()

    override func viewDidLoad() {
        super.viewDidLoad()
        service.load()
    }
}

我的测试类就是这样的:

class MyViewController Tests: XCTestCase {

     var vc: MyViewController!
     var serviceMock = ServiceMock()

    override func setUp() {
       super.setUp()
       let storyboard = UIStoryboard(name: "Main", bundle: nil)
       vc = storyboard.instantiateViewController(withIdentifier: "MyViewController") as! MyViewController
       vc.service = serviceMock
    }
}

func testThatServiceIsCalled() {

       XCTAssertTrue(serviceMock.loadCalled)
 }

这里显而易见的问题是,当我实例化viewController时调用viewDidLoad(),并且测试失败,因为模拟没有正确注入。

有解决方案吗

答案

为什么需要使用故事板来创建视图控制器?

这不行吗?

func testThatServiceIsCalled() {
  let vc = MyViewController()
  vc.service = serviceMock
  vc.viewDidLoad()

  XCTAssertTrue(serviceMock.loadCalled)
}
另一答案

TL; DR您不应该像这样单元测试与UI相关的方法。

控制器和视图不适合单元测试,原因很简单,因为它们通常涉及在屏幕上反映的操作,因此(非常)难以测试。快照测试或UI自动化测试是MVC这两个组件的更好选择。

编写良好的Controller不包含业务逻辑,它将UI内容委托给View,并将业务操作委托给其Model。考虑到这一点,它应该是可以进行单元测试的模型。

现在,如果你真的想断言你的服务是用正确的方法调用的,你可以将VC设置为root视图控制器,这应该确保loadView方法获得调用者,这应该触发viewDidLoad

func testThatServiceIsCalled() {
    let window = UIWindow(frame:  UIScreen.main.bounds)
    window.makeKeyAndVisible()
    window.rootViewController = vc
    XCTAssertTrue(serviceMock.loadCalled)
}

以上是关于如何对`viewDidLoad()`进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章

Swift 单元测试 - 等待 viewDidLoad

Django单元测试测试视图问题,怎么解决

如何测试自定义单元格是不是已向 tableView 注册?

单元测试(Kiwi):调用 loadView 和 viewDidLoad 后,测试中的属性始终为零

iOS 单元测试:如何对 firstResponderStatus 进行单元测试

如何对 ETL 流程进行测试(单元测试)?