Created
April 16, 2018 09:06
-
-
Save janodev/3fcf6fcf0f87c0fc79dafc75f276263b to your computer and use it in GitHub Desktop.
Unit testing a view controller
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// From https://albertodebortoli.com/2018/03/12/easy-view-controller-unit-testing/ | |
import XCTest | |
import UIKit | |
class ControllerLifecycle<T: UIViewController> | |
{ | |
private lazy var this = type(of: self).self | |
private var rootWindow: UIWindow? | |
var rootController: T? { | |
return rootWindow?.rootViewController as? T | |
} | |
func setupWindow(storyboardName: String, controllerIdentifier: String) | |
{ | |
let bundle = Bundle(for: T.self) | |
guard let storyboard = this.createStoryboard(name: storyboardName, bundle: bundle), | |
let controller = this.createController(storyboard: storyboard, identifier: controllerIdentifier) | |
else { | |
return | |
} | |
setupWindow(withViewController: controller) | |
} | |
func setupWindow(withViewController viewController: T) | |
{ | |
rootWindow = UIWindow(frame: UIScreen.main.bounds) | |
guard let rootWindow = rootWindow else { return } | |
rootWindow.isHidden = false | |
rootWindow.rootViewController = viewController | |
_ = viewController.view | |
viewController.viewWillAppear(false) | |
viewController.viewDidAppear(false) | |
} | |
func tearDownWindow() { | |
guard let rootWindow = rootWindow, let rootViewController = rootWindow.rootViewController as? T else { | |
XCTFail("Expected to find a window with a root view controller. However: rootWindow = \(String(describing: self.rootWindow)), rootViewController = \(String(describing: self.rootWindow?.rootViewController)).") | |
return | |
} | |
rootViewController.viewWillDisappear(false) | |
rootViewController.viewDidDisappear(false) | |
rootWindow.rootViewController = nil | |
rootWindow.isHidden = true | |
self.rootWindow = nil | |
} | |
/// Return a storyboard for the given name and bundle. Log a console error if not found. | |
private static func createController(storyboard: UIStoryboard, identifier: String) -> T? { | |
var controller: T? = nil | |
do { | |
try ObjC.catchException { | |
controller = storyboard.instantiateViewController(withIdentifier: identifier) as? T | |
} | |
} catch { | |
print("🚨 Storyboard \(storyboard) doesn't contain a view controller with identifier ‘\(identifier)’.") | |
} | |
return controller | |
} | |
/// Return a storyboard for the given name and bundle. Log a console error if not found. | |
private static func createStoryboard(name: String, bundle: Bundle) -> UIStoryboard? { | |
var storyboard: UIStoryboard? = nil | |
do { | |
try ObjC.catchException { | |
storyboard = UIStoryboard(name: name, bundle: bundle) | |
} | |
} catch { | |
print("🚨 Failed to create storyboard \(name): \(error)") | |
} | |
return storyboard | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import XCTest | |
import UIKit | |
@testable import Foobar | |
class ViewControllerTests: XCTestCase | |
{ | |
private typealias Controller = ViewController | |
private lazy var this = type(of: self).self | |
private var controllerLifecycle: ControllerLifecycle<Controller>? | |
override func setUp() { | |
super.setUp() | |
controllerLifecycle = ControllerLifecycle<Controller>() | |
controllerLifecycle?.setupWindow(storyboardName: "Main", controllerIdentifier: "ViewController") | |
if let controller = controllerLifecycle?.rootController { | |
print("Stub \(controller)") | |
} | |
} | |
func testFoo(){ | |
print("this is here to trigger setUp() and tearDown()") | |
} | |
override func tearDown() { | |
controllerLifecycle?.tearDownWindow() | |
controllerLifecycle = nil | |
super.tearDown() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment