Unit Testing UITabBarControllers
Previously, I wrote about how to unit test UIViewController. However, in the real world, a UIViewController
is usually embedded in a UINavigationController
and a UITabBarController
.
There are a couple ways to setup unit tests in this case. First of all, you can reach through the controller stack to setup the UIViewController
that is the system under test.
var sut: FirstViewController!
override func setUp() {
super.setUp()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tab = storyboard.instantiateInitialViewController() as! UITabBarController
UIApplication.shared.keyWindow?.rootViewController = tab
let nav = tab.selectedViewController as! UINavigationController
sut = nav.topViewController as! FirstViewController
UIApplication.shared.keyWindow?.rootViewController = sut
}
Note that you have to assign the UITabBarController
to the rootViewController
to run the view lifecycle and then assign the UIViewController
to the rootViewController
to run its view lifecycle.
Once again, you should not directly call loadView
.
A UITabBarController
owns an array of viewControllers. The selectedIndex
variable can changed to select another UIViewController
to test. Once again, make sure to assign it to rootViewController
to run the view lifecycle methods.
var sut: SecondViewController!
override func setUp() {
super.setUp()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tab = storyboard.instantiateInitialViewController() as! UITabBarController
UIApplication.shared.keyWindow?.rootViewController = tab
tab.selectedIndex = 1
let nav = tab.selectedViewController as! UINavigationController
sut = nav.topViewController as! SecondViewController
UIApplication.shared.keyWindow?.rootViewController = sut
}
The above code can be simplified by directly instantiating the UIViewController
.
var sut: SecondViewController!
override func setUp() {
super.setUp()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
sut = storyboard.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
UIApplication.shared.keyWindow?.rootViewController = sut
}
The above code is simpler but it does not ensure that the UIViewController
is in the viewController array.