12

このトピックに関する既存の質問がいくつかありますが、それらは私が求めているものではありません。私は自分のアプリ用に、2 つのUIAlertControllerインスタンスを表示する小さな Swift アプリ レーティング プロンプトを作成しました。一方は他方によってトリガーされます。

私は今、これを単体テストしようとしており、テストでその 2 番目のアラートに到達しようとしています。最初のコントローラーをチェックするための簡単なスパイを作成しましたが、最初のアラートでアクションの 1 つをトリガーし、次に 2 番目のアラートを表示する方法が必要です。

私はすでに試しましたalert.actions.first?.accessibilityActivate()が、そのアクションのハンドラー内で壊れているようには見えませんでした。それが私が求めているものです。

4

4 に答える 4

5

私がやったことは大まかに次のとおりです。

  1. アラート コントローラーを表示するクラスのモック バージョンを作成し、単体テストでこのモックを使用しました。

  2. モックされていないバージョンで作成した次のメソッドをオーバーライドしました。

    func alertActionWithTitle(title: String?, style: UIAlertActionStyle, handler: Handler) -> UIAlertAction
    
  3. オーバーライドされた実装では、アクションに関するすべての詳細をいくつかのプロパティに格納しました (Handlerこれは単なる typealias です() -> (UIAlertAction)) 。

    var didCreateAlert = false
    var createdTitles: [String?] = []
    var createdStyles: [UIAlertActionStyle?] = []
    var createdHandlers: [Handler?] = []
    var createdActions: [UIAlertAction?] = []
    
  4. 次に、テストを実行するときに、アラートのパスをトラバースするためにcallHandlerAtIndex、ハンドラーを反復処理して正しいハンドラーを実行するメソッドを実装しました。

これは、私のテストが次のようになることを意味します。

feedback.start()
feedback.callHandlerAtIndex(1) // First alert, second action
feedback.callHandlerAtIndex(2) // Second alert, third action
XCTAssertTrue(mockMailer.didCallMail)
于 2016-04-05T07:42:32.307 に答える
0

上記の Luke のガイダンスを使用してUIAlertAction、完了ブロックを保存するサブクラスを作成し、テスト中に呼び出すことができるようにしました。

class BSAlertAction: UIAlertAction {

    var completionHandler: ((UIAlertAction) -> Swift.Void)?

    class func handlerSavingAlertAction(title: String?,
                                        style: UIAlertActionStyle,
                                        completionHandler: @escaping ((UIAlertAction) -> Swift.Void)) -> BSAlertAction {
        let alertAction = self.init(title: title, style: style, handler: completionHandler)
        alertAction.completionHandler = completionHandler
        return alertAction
    }

}

必要に応じて、これをカスタマイズして、より多くの情報 (タイトルやスタイルなど) を保存できます。次に、この実装を使用する XCTest の例を次に示します。

func testThatMyMethodGetsCalled() {
    if let alert = self.viewController?.presentedViewController as? UIAlertController,
        let action = alert.actions[0] as? BSAlertAction,
        let handler = action.completionHandler {
            handler(action)
            let calledMyMethod = self.presenter?.callTrace.contains(.myMethod) ?? false
            XCTAssertTrue(calledMyMethod)
    } else {
        XCTFail("Got wrong kind of alert when verifying that my method got called“)
    }
}
于 2018-09-23T14:08:18.773 に答える