Edited at

[iOS、Swift] ユニットテストの時に、任意のタイミングでViewDidLoad()、ViewWill(Did)Appear()、ViewWill(Did)Disappear()を呼び出す方法

More than 1 year has passed since last update.

忘れがちなので備忘も兼ねてまとめておきます。


事前準備

以下のようなView Controller(Initial View Controller)を作成します。


HogeViewController.swift


import UIKit

class HogeViewController: UIViewController {

// ViewDidLoad()用フラグ
var isViewDidLoadCalled = false

// ViewWill(Did)Appear()用フラグ
var isViewWillAppearCalled = false
var isViewDidAppearCalled = false

// ViewWill(Did)Disappear()用フラグ
var isViewWillDisappearCalled = false
var isViewDidDisappearCalled = false

// MARK: - View Controller Lifecycle Methods
override func viewDidLoad() {
super.viewDidLoad()
self.isViewDidLoadCalled = true
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.isViewWillAppearCalled = true
}

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.isViewDidAppearCalled = true
}

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.isViewWillDisappearCalled = true
}

override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
self.isViewDidDisappearCalled = true
}
}


次に、このView Controllerをテストするファイルを作成し、以下のようなセットアップを行います。


HogeViewControllerTests.swift


import XCTest
@testable import InvokeVCLifecycleMethods

class HogeViewControllerTests: XCTestCase {

var hogeVC: HogeViewController!

override func setUp() {
super.setUp()

let storyboard = UIStoryboard(name: "Main", bundle: nil)

hogeVC = storyboard.instantiateInitialViewController() as! HogeViewController
}

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

func test_ViewDidLoad_Called() {
XCTAssertTrue(hogeVC.isViewDidLoadCalled)
}

func test_ViewWillAndDidAppear_Called() {
XCTAssertTrue(hogeVC.isViewWillAppearCalled)
XCTAssertTrue(hogeVC.isViewDidAppearCalled)
}

func test_ViewWillAndDidDisappear_Called() {
XCTAssertTrue(hogeVC.isViewWillDisappearCalled)
XCTAssertTrue(hogeVC.isViewDidDisappearCalled)
}

}


この状態でテストを実行すると、全てのテストがFailします。

これで事前準備は完了です。


View Controller LifeCycleメソッドを呼び出す

それでは早速、各種メソッドを呼び出していきましょう。


ViewDidLoad()

ViewDidLoad()は、View Controllerのviewプロパティにアクセスすることで呼び出せます。

[追記] @kazuhiro4949さんより、viewへのアクセスではなくloadViewIfNeeded()ViewDidLoad()を呼び出す方法を教えていただきました。ありがとうございます!

    func test_ViewDidLoad_Called() {

// ViewDidLoad()を呼び出す
hogeVC.loadViewIfNeeded()

XCTAssertTrue(hogeVC.isViewDidLoadCalled)
}

結果

Passしました。


ViewWill(Did)Appear()

ViewWillAppear()は、UIViewControllerにbeginAppearanceTransition(_:animated:)というインスタンスメソッドが用意されており、その第一引数(_ isAppearing: Bool)をtrueにして呼ぶことで呼び出せます。ViewDidAppear()は、そのインスタンスメソッドを呼んだ後にendAppearanceTransition()を呼ぶことで呼び出せます。

        // ViewWillAppear()を呼び出す(第一引数をtrueにする)

hogeVC.beginAppearanceTransition(true, animated: false)
// ViewDidAppear()を呼び出す
hogeVC.endAppearanceTransition()

結果

これもPassしました。


ViewWill(Did)Disappear()

ViewWillDisappear()は、先程のbeginAppearanceTransition(_:animated:)の第一引数(_ isAppearing: Bool)をfalseにして呼ぶことで呼び出せます。ViewDidDisappear()は、その後にendAppearanceTransition()を呼ぶことで呼び出せます。

    func test_ViewWillAndDidDisappear_Called() {

// ViewWillDisappear()を呼び出す(第一引数をfalseにする)
hogeVC.beginAppearanceTransition(false, animated: false)
// ViewDidDisappear()を呼び出す
hogeVC.endAppearanceTransition()

XCTAssertTrue(hogeVC.isViewWillDisappearCalled)
XCTAssertTrue(hogeVC.isViewDidDisappearCalled)
}

結果

全てPassしました。

ユニットテストを書く時にご活用ください。


参考

Work with View Controllers

https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/WorkWithViewControllers.html)

[追記] loadViewIfNeeded()

https://developer.apple.com/documentation/uikit/uiviewcontroller/1621446-loadviewifneeded

beginAppearanceTransition(_:animated:)

https://developer.apple.com/documentation/uikit/uiviewcontroller/1621387-beginappearancetransition

endAppearanceTransition()

https://developer.apple.com/documentation/uikit/uiviewcontroller/1621503-endappearancetransition

iOS: The One Weird Trick For Testing View Controllers in Swift

Testing in Swift