簡體   English   中英

測試 UIAlertController 是否已呈現

[英]Testing if UIAlertController has been presented

我有一個協議,用於允許我的 ViewControllers 顯示警報。

import UIKit

struct AlertableAction {
    var title: String
    var style: UIAlertAction.Style
    var result: Bool
}

protocol Alertable {
    func presentAlert(title: String?, message: String?, actions: [AlertableAction], completion: ((Bool) -> Void)?)
}

extension Alertable where Self: UIViewController {
    func presentAlert(title: String?, message: String?, actions: [AlertableAction], completion: ((Bool) -> Void)?) {
        let generator = UIImpactFeedbackGenerator(style: .medium)
        generator.impactOccurred()
        let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
        actions.forEach { action in
            alertController.addAction(UIAlertAction(title: action.title, style: action.style, handler: { _ in completion?(action.result) }))
        }
        present(alertController, animated: true, completion: nil)
    }
}

我稱之為

   @objc private func didTapLogout() {
        presentAlert(
            title: nil, message: "Are you sure you want to logout?",
            actions: [
                AlertableAction(title: "No", style: .cancel, result: false),
                AlertableAction(title: "Yes", style: .destructive, result: true),
            ],
            completion: { [weak self] result in
                guard result else { return }
                self?.presenter.logout()
            }
        )
    }

我想編寫一個單元測試來在調用時斷言,呈現的視圖控制器是UIAlertController

我正在嘗試類似的東西,但它沒有通過

    func test_renders_alert_controller() {
        sut.show()

        XCTAssertNotNil(sut.presentedViewController)
    }

    class MockViewController: UIViewController, Alertable {

        var presentViewControllerTarget: UIViewController?

        func show() {
            presentAlert(title: nil, message: "Are you sure you want to logout?", actions:
                [AlertableAction(title: "No", style: .cancel, result: false)],
                completion: nil
            )

            self.presentViewControllerTarget = self.presentedViewController
        }
    }

在運行斷言之前,您需要等待UIAlertController完全可見。

查看XCTWaiter

嘗試類似以下內容:

    let nav = UINavigationController.init(rootViewController: sut)

    sut.show()

    let exp = expectation(description: "Test after 1.5 second wait")
    let result = XCTWaiter.wait(for: [exp], timeout: 1.5)
    if result == XCTWaiter.Result.timedOut {
        XCTAssertNotNil(nav.visibleViewController is UIAlertController)
    } else {
        XCTFail("Delay interrupted")
    }

ViewControllerPresentationSpy通過捕獲用於呈現警報的信息來避免緩慢、不穩定的單元測試,而不實際呈現任何警報。 您只需要創建一個 AlertVerifier,然后調用任何顯示您的警報的內容:

let alertVerifier = AlertVerifier()

sut.show()

alertVerifier.verify(
    title: nil,
    message: "Are you sure you want to logout?",
    animated: true,
    presentingViewController: sut,
    actions: [
        .cancel("No"),
        .destructive("Yes"),
    ]
)

此驗證方法檢查:

  • 出現了一個帶有動畫的警報。
  • 呈現視圖控制器是被測系統。
  • 警報標題。
  • 警報消息。
  • UIAlertController.Style的優選式( .alert默認情況下)
  • 每個動作的標題和樣式。

您可以按名稱調用每個操作:

try alertVerifier.executeAction(forButton: "Yes")

(將測試標記為throws 。如果沒有給定名稱的按鈕,則測試將失敗。)

試試看它與 1.5 秒超時相比有多快。 還要比較你可以測試多少。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM