如何对 `viewDidLoad()` 进行单元测试
How to unit test `viewDidLoad()`
在 iOS 上对 UIViewController.viewDidLoad()
方法进行单元测试时,每个人最喜欢的注入依赖项的方式是什么?
鉴于我的实施是:
class MyViewController: UIViewController {
var service: Service = Service()
override func viewDidLoad() {
super.viewDidLoad()
service.load()
}
}
我的测试 class 是这样的:
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 时被调用,并且测试失败,因为模拟没有正确注入。
有什么解决办法吗?
TL;DR 你不应该像这样对 UI-related 方法进行单元测试。
控制器和视图不适合进行单元测试,原因很简单,因为它们通常涉及反映在屏幕上的操作,因此(非常)难以测试。快照测试或 UI 自动化测试更适合 MVC.
的这两个组件
well-written 控制器不包含业务逻辑,它将 UI 内容委托给视图,将业务操作委托给它的模型。考虑到这一点,应该对模型进行单元测试。
现在,如果你真的想断言你的服务是用正确的方法调用的,你可以将你的 VC 设置为根视图控制器,这应该确保 loadView
方法被调用,这应该触发 viewDidLoad
一个:
func testThatServiceIsCalled() {
let window = UIWindow(frame: UIScreen.main.bounds)
window.makeKeyAndVisible()
window.rootViewController = vc
XCTAssertTrue(serviceMock.loadCalled)
}
为什么需要使用故事板来创建视图控制器?
这不行吗?
func testThatServiceIsCalled() {
let vc = MyViewController()
vc.service = serviceMock
vc.viewDidLoad()
XCTAssertTrue(serviceMock.loadCalled)
}
在 iOS 上对 UIViewController.viewDidLoad()
方法进行单元测试时,每个人最喜欢的注入依赖项的方式是什么?
鉴于我的实施是:
class MyViewController: UIViewController {
var service: Service = Service()
override func viewDidLoad() {
super.viewDidLoad()
service.load()
}
}
我的测试 class 是这样的:
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 时被调用,并且测试失败,因为模拟没有正确注入。
有什么解决办法吗?
TL;DR 你不应该像这样对 UI-related 方法进行单元测试。
控制器和视图不适合进行单元测试,原因很简单,因为它们通常涉及反映在屏幕上的操作,因此(非常)难以测试。快照测试或 UI 自动化测试更适合 MVC.
的这两个组件well-written 控制器不包含业务逻辑,它将 UI 内容委托给视图,将业务操作委托给它的模型。考虑到这一点,应该对模型进行单元测试。
现在,如果你真的想断言你的服务是用正确的方法调用的,你可以将你的 VC 设置为根视图控制器,这应该确保 loadView
方法被调用,这应该触发 viewDidLoad
一个:
func testThatServiceIsCalled() {
let window = UIWindow(frame: UIScreen.main.bounds)
window.makeKeyAndVisible()
window.rootViewController = vc
XCTAssertTrue(serviceMock.loadCalled)
}
为什么需要使用故事板来创建视图控制器?
这不行吗?
func testThatServiceIsCalled() {
let vc = MyViewController()
vc.service = serviceMock
vc.viewDidLoad()
XCTAssertTrue(serviceMock.loadCalled)
}