如何测试UIAlertController

时间:2018-01-14 05:15:42

标签: ios swift uialertcontroller xctest

我正在测试一个呈现UIAlertController的函数,但测试仍然失败。这就是函数的样子:

func presentBuyingErrorDiaologue() {
    let alert = UIAlertController(title: "Warning", message: "Error purchasing item, please retry this action. If that doesn't help, try restarting or reinstalling the app.", preferredStyle: .alert)
    let okButton = UIAlertAction(title: "OK", style: .default)
    alert.addAction(okButton)
    self.present(alert, animated: true, completion: nil)
}

由于此函数位于名为ShopViewController的类中,因此我假设测试此函数的正确方法是调用函数shopViewController.presentBuyingErrorDiaologue(),然后使用XCTAssertTrue(shopViewController.presentedViewController is UIAlertController)。但是,当我运行测试时,assert语句失败。测试UIAlertController是呈现视图的正确方法是什么?

3 个答案:

答案 0 :(得分:3)

在测试其可见性之前,您应该等待UIAlertController完全呈现,因此您可能会尝试按照以下方式更改测试:

import XCTest

class UIAlertControllerTests: XCTestCase {

    func presentBuyingErrorDialogue() {
      let alert = UIAlertController(title: "Warning", message: "Error purchasing item, please retry this action. If that doesn't help, try restarting or reinstalling the app.", preferredStyle: .alert)
      let okButton = UIAlertAction(title: "OK", style: .default)
      alert.addAction(okButton)
      UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: true, completion: nil)
    }

    func testPresentBuyingErrorDialogue() {
      self.presentBuyingErrorDialogue()
      let expectation = XCTestExpectation(description: "testExample")
      DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
        XCTAssertTrue(UIApplication.shared.keyWindow?.rootViewController?.presentedViewController is UIAlertController)
        expectation.fulfill()
      })
      wait(for: [expectation], timeout: 1.5)
   }
}

您可以使用UIApplication.shared.keyWindow?.rootViewController更改ShopViewController

答案 1 :(得分:2)

  1. MockUIAlertController添加到测试目标
  2. 为测试目标设置桥接标头
  3. #import <MockUIAlertController/QCOMockAlertVerifier.h>添加到该桥接标题
  4. 在测试呼叫shopViewController.presentBuyingErrorDiaologue()
  5. 之前实例化QCOMockAlertVerifier
  6. 验证QCOMockAlertVerifier
  7. 捕获的各种值

    除了捕获值之外,QCOMockAlertVerifier还可以让您轻松执行具有给定标题的警报按钮的操作。

    测试不需要等待期望,所以它们超级快。

    How to Test UIAlertControllers (and Control Swizzling)了解详情。

答案 2 :(得分:0)

您可以使用completion方法的present参数在出现警报时获取回调,从而确定是否显示警报。 (请注意,此方法更多是关于断言执行了正确的操作,而不是显示了正确的视图控制器类型)。

要实现此功能,您必须在completion方法中添加presentBuyingErrorDialogue参数,但是您可以为其设置默认值nil,这样就不会打扰你的非测试代码。 (当然,您也可以在有意义的情况下在应用程序代码中使用它,例如在出现警报时启动背景动画)。

以下是视图控制器的修改代码:

class ShopViewController: UIViewController {
  func presentBuyingErrorDialogue(completion: (() -> ())? = nil) {
    let alert = UIAlertController(title: "Warning", message: "...", preferredStyle: .alert)
    let okButton = UIAlertAction(title: "OK", style: .default)
    alert.addAction(okButton)
    self.present(alert, animated: true, completion: completion)
  }
}

这是一个简单的测试可能看起来像(忽略rootViewController的任何清理):

class ShopViewControllerTests: XCTestCase {
  func testErrorAlert() {
    let vc = ShopViewController()
    UIApplication.shared.keyWindow?.rootViewController = vc
    let exp = expectation(description: "shows alert")
    vc.presentBuyingErrorDialogue {
      exp.fulfill()
    }
    waitForExpectations(timeout: 1)
  }
}

在应用程序代码中,您仍然可以像以前一样使用该方法,而无需提供该回调块:

let vc = ShopViewController()
vc.presentBuyingErrorDialogue()