繁体   English   中英

如何单元测试`viewDidLoad()`

[英]How to unit test `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)
 }

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

有什么解决办法吗?

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

这行不通?

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

  XCTAssertTrue(serviceMock.loadCalled)
}

TL;DR 你不应该像这样对 UI 相关的方法进行单元测试。

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

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

现在,如果你真的想断言你的服务被正确的方法调用,你可以将你的 VC 设置为根视图控制器,这应该确保loadView方法被调用,这应该触发viewDidLoad一个:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM