LoginSignup
5
4

More than 5 years have passed since last update.

[Swift] UIAlertViewControllerもモックでテストする

Posted at

はじめに

皆様、ユニットテストされていますか?
Model周りはテストしやすいですが、ViewController周りはテストしずらいですよね。

今日は、モックを使って、UIAlertViewController(Alert)をテストする方法をご紹介します。

ユニットテストの種類

テストの種類 説明
スタブ メソッドの戻り値にダミーの値を返すこと
モック メソッドが呼ばれているか、プロパティに値がセットされているか確認すること
パーシャルモック 既存のクラスのうち一部のメソッドをモック化すること

プロトコルを利用して、モック化する

UIAlertViewControllerのAlertを例に説明します。

プロトコル

DialogPresenter.swift
import UIKit

protocol DialogPresenter {
    func present(title: String, message: String?, onOK: (Void -> Void),
                 onTopOf presenter: UIViewController)
}

OKとCancelボタン付きのアラート

OKCancelDialogPresenter.swift
import UIKit

class OKCancelDialogPresenter: DialogPresenter {

    func present(title: String, message: String?, onOK: (Void -> Void),
                 onTopOf presentingViewController: UIViewController) {

        let alert = UIAlertController(title: title, message: message, preferredStyle: .Alert)

        let cancelAction = UIAlertAction(title: "Cancel", style: .Cancel, handler: nil)
        alert.addAction(cancelAction)

        let okAction = UIAlertAction(title: "OK", style: .Default) { _ in onOK() }
        alert.addAction(okAction)

        presentingViewController.presentViewController(alert, animated: true, completion: nil)
    }
}

ViewControllerから呼ぶ

ボタンが押下されたら、ダイアログを表示する

ViewController.swift
    @IBAction func didTapButton(sender: UIButton) {

        OKCancelDialogPresenter().present("タイトル",
                                          message: "メッセージ",
                                      onOK: { (Void) in
                                        print(#function)
            },
                                      onTopOf: self)
    }

モックを作る

メソッドが呼ばれたか、プロパティに正しく値がセットされているか確認する

MocDialogPresenter.swift
import UIKit

class MocDialogPresenter: DialogPresenter {

    var present_wasCalled = false
    var present_wasCalled_withArgs: (title: String, message: String?,
        onOK: (Void -> Void), presentingVC: UIViewController)? = nil

    func present(title: String, message: String?, onOK: (Void -> Void),
                 onTopOf presenter: UIViewController) {

        present_wasCalled = true
        present_wasCalled_withArgs = (title: title, message: message, onOK: onOK, presentingVC: presenter)
    }
}

ユニットテストする

DialogTest.swift
import XCTest

class DialogTest: XCTestCase {

    override func setUp() {
        super.setUp()
    }

    override func tearDown() {
        super.tearDown()
    }

    func testOKCancelDialog() {

        let dialog = MocDialogPresenter()

        dialog.present("タイトル",
                       message: "メッセージ",
                       onOK: { (Void) in },
                       onTopOf: UIViewController())

        XCTAssertTrue(dialog.present_wasCalled)
        XCTAssertEqual("タイトル", dialog.present_wasCalled_withArgs?.title)
        XCTAssertEqual("メッセージ", dialog.present_wasCalled_withArgs?.message)
        XCTAssertNotNil(dialog.present_wasCalled_withArgs?.onOK)
        XCTAssertNotNil(dialog.present_wasCalled_withArgs?.presentingVC)
    }
}

まとめ

プロトコルを利用してモック化する方法をご紹介しました。
ViewControllerからPresenterに切り出せる処理は、
ユニットテストしていきたいと思います。

参考記事

下記の記事を参考に纏めさせて頂きました。
大変勉強になりました。

https://realm.io/jp/news/rachel-bobbins-testing-view-controllers-quick/
https://realm.io/jp/news/tryswift-veronica-ray-real-world-mocking-swift/

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4