首页 > 解决方案 > 快速单元测试异步函数

问题描述

我正在为 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在执行测试用例之前确保函数完成运行的最佳方法是什么?

标签: swiftunit-testingasynchronousuibutton

解决方案


performLogin在执行测试用例之前确保函数完成运行的最佳方法是什么?

一般来说,最好的方法是让您的测试调用performLogin函数。不要使用单元测试来触发或测试接口行为。仅测试业务逻辑,并以使其可测试的方式分离出该业务逻辑。

但是,在您的情况下,您可能一直在这里编写的是 UI 测试,而不是单元测试。(我真的不能说,因为我不知道你在想什么,这种情况应该是可测试的。)


推荐阅读