Testing Push Onto The Navigation Stack
Last month my book about Test-Driven Development with Swift finally got published. In this and some of the next blog posts I will present some things I learned while I wrote it.
In this post I will show a nice way to test if a view controller got pushed onto the navigation stack as a result of an event.
Let’s say we have button on a view controller. When the user taps the button, a detail view controller should be pushed onto the navigation stack. How can we test this?
Easy! We will use a mock for the navigation controller. The mock looks like this:
class MockNavigationController: UINavigationController {
var pushedViewController: UIViewController?
override func pushViewController(viewController: UIViewController, animated: Bool) {
pushedViewController = viewController
super.pushViewController(viewController, animated: true)
}
}
To be precise, this is a partial mock. It is a subclass of UINavigationController
and it overrides only one method of the superclass. This mock registers
when pushViewController(_:animated:)
is called and stores the view controller that got passed into the method
as the first parameter.
The test would look like this:
func testTappingPushButton_PushesDetailViewControllerOntoStack() {
let viewController = ViewController()
let navigationController = MockNavigationController(rootViewController: viewController)
UIApplication.sharedApplication().keyWindow?.rootViewController = navigationController
guard let view = viewController.view as? View else { XCTFail(); return }
view.button.sendActionsForControlEvents(.TouchUpInside)
XCTAssertTrue(navigationController.pushedViewController is DetailViewController)
}
First, we arrange the view controller to be the rootViewController
of an instance of our navigation controller mock. Then we set the
navigation controller to be the rootViewController
of the keyWindow
of the UIApplication
singleton. This is needed because to be able to push a view controller
onto the navigation stack, the view of the view controller has to be in
the view hierarchy.
Next, we get the button and send it all actions for the control events
.TouchUpInside
. Finally we assert that the pushed view controller is of type
DetailViewController
.
You can find the code on github.
You can find a lot more about how to test real world examples in my book. Please don’t forget to let me know what you think about the book when you read it.