swift - 快速单元测试异步函数
问题描述
我正在为 UI 的各种组件编写单元测试。但是,在为触发异步功能的按钮编写测试时,我遇到了麻烦。我的问题是我正在使用UIButton.sendActions(for controlEvents: UIControlEvents)
触发按钮的按下,然后调用异步函数。
假设我有一个测试:
func testLoginToMainScene() {
loadView()
let queue = DispatchQueue(label: "LoginButtonPressed")
queue.sync {
view.loginButton.sendActions(for: .touchUpInside)
}
XCTAssertTrue(router.navigateToMainSceneCalled)
}
这会测试一个类中的以下代码LoginViewController
:
@IBAction func loginButtonPressed(_ sender: AnyObject) {
hideKeyboard()
performLogin(email: emailTextField.text, password: passwordTextField.text)
}
还有一个通过调用 redux worker 的方法来处理登录的函数:
private func performLogin(email: String, password: String) {
let result = myReduxWorker.getStore().dispatch(newLoginAction(email: email, password: password)
if let promise = result as? Promise<[String: Any]> {
promise.done { json -> Void in
//Login was successful!
router.navigateToMainScene()
}
}
目前,测试失败是因为XCTAssertTrue
测试在performLogin
函数完成之前运行,因此 beforenavigateToMainScene
被调用。我尝试使用 a DispatchQueue
,但是一旦将.touchUpInside
操作发送到按钮,内部的代码块就.sync
完成了,并且测试功能继续并运行XCTAssertTrue
测试。
performLogin
在执行测试用例之前确保函数完成运行的最佳方法是什么?
解决方案
performLogin
在执行测试用例之前确保函数完成运行的最佳方法是什么?
一般来说,最好的方法是让您的测试调用该performLogin
函数。不要使用单元测试来触发或测试接口行为。仅测试业务逻辑,并以使其可测试的方式分离出该业务逻辑。
但是,在您的情况下,您可能一直在这里编写的是 UI 测试,而不是单元测试。(我真的不能说,因为我不知道你在想什么,这种情况应该是可测试的。)
推荐阅读
- node.js - Angular如何在组件中使用嵌入脚本
- php - 字符串编码为 utf-8 后,img 获取 404 的请求结果
- docker - Logstash 未在 Docker compose 中公开端口 5044
- elasticsearch - 重新索引完成后自动删除 Elasticsearch 索引
- html - 设计孩子而不是孙子?
- python - 从字典中获取 ID 列表的 Pythonic 方式
- aframe - A-frame 在手机中显示为 3d 图像,而不是 WebVR 体验
- deep-learning - 图像分类 Pytorch
- android - 我关于在 Android 应用中添加谷歌广告的问题
- react-native - Flexbox 布局反应原生 - 第一个视图占据整个屏幕