I'm writing unit tests for various components of a UI. However, I'm running into trouble when writing tests for buttons that trigger asynchronous functions. My problem is that I'm using the UIButton.sendActions(for controlEvents: UIControlEvents) to trigger the pressing of the button, which then calls an asynchronous function.
Say I have a test:
func testLoginToMainScene() {
     loadView()
     let queue = DispatchQueue(label: "LoginButtonPressed")
     queue.sync {
          view.loginButton.sendActions(for: .touchUpInside)
     }
     XCTAssertTrue(router.navigateToMainSceneCalled)
}
That tests the following bit of code in a LoginViewController class:
@IBAction func loginButtonPressed(_ sender: AnyObject) {
     hideKeyboard()
     performLogin(email: emailTextField.text, password: passwordTextField.text)
}
And a function that handles the login by calling a method of a 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()
          }
     }
Currently, the test fails because the XCTAssertTrue test runs before the performLogin function completes, and thus before navigateToMainScene is called. I tried using a DispatchQueue, but as soon as the .touchUpInside action is sent to the button, the block of code inside the .sync finishes, and the test function continues and runs the XCTAssertTrue test.
What is the best way to ensure that the performLogin function has finished running before executing the test case?
 
    