【发布时间】:2018-11-18 19:19:24
【问题描述】:
我正在为 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 函数完成之前运行,因此在调用navigateToMainScene 之前。我尝试使用DispatchQueue,但只要将.touchUpInside 操作发送到按钮,.sync 内的代码块就会完成,并且测试函数会继续运行XCTAssertTrue 测试。
在执行测试用例之前确保performLogin 函数已完成运行的最佳方法是什么?
【问题讨论】:
-
你知道XCTestExpectation吗?
-
@matt 是的,我尝试使用期望值,但
sendActions函数是“一劳永逸”类型,没有完成处理程序可以挂钩来满足期望值。 -
当你应该写一个 Ui 测试时,这几乎就像你在写一个单元测试。
-
另一种看待它的方式是:您遇到此问题的事实是异味。你正在测试错误的东西,错误的方式。单元测试用于业务逻辑。您不应该“按下”任何按钮。不要测试已知有效的方法;不要测试 Cocoa 框架的行为。
标签: swift unit-testing asynchronous uibutton