I want to make a unit test to see if a view controller is presenting another view controller.
func testMainTabController_WhenActionButtonIsTapped_NewSuppliersInvoiceControllerIsCreatedV2() {
let sut = MainTabBarController()
sut.loadViewIfNeeded()
let myExpectation = expectation(description: "The sut should present a view controller")
sut.actionButton.sendActions(for: .touchUpInside)
if let x = sut.presentedViewController {
myExpectation.fulfill()
} else {
XCTFail("The view controller was not presented")
}
wait(for: [myExpectation], timeout: 3)
}
Here the result I obtain is fail test. Because I get nil as a presentedViewController. This is the code of the button
@objc func handleActionButtonTap() {
let suppliersInvoiceController = SuppliersInvoiceController()
let navCon = UINavigationController(rootViewController: suppliersInvoiceController)
navCon.modalPresentationStyle = .fullScreen
present(navCon, animated: true, completion: nil)
}
This is the code I wrote in the test. The code in the button is successfully called when I run the unit test and the present method is called. Of course if I run the app it works properly.
When I tap the button, I get my presented view controller.
If I type let vc = presentedViewController inside handleActionButtonTap() and print(vc) I get the nav con as a result. But why can’t I do it inside the unit test?
Does anybody has a clue of whats going on?
Thanks
2
Answers
What you want is to do
UITest
and notUnitTest
.What is a Unit Test? https://x-team.com/blog/how-to-get-started-with-ios-unit-tests-in-swift/
So going back to the answer, do UI Testing for that. Here’s a sample cheat sheet for doing UI Tests after a google search: https://github.com/joemasilotti/UI-Testing-Cheat-Sheet
In UI Testing, you will be able to check if a screen was pushed or presented after tapping on a button or something, like for example:
Does you viewController have enough context for presentViewController:animated: to work? for example, it has no window. PresentViewController:animated: does different things in "horizontally regular environment" etc.
If you want to unit test, how about changing the VC to not present other VC’s directly from itself, instead have it call a method on e.g. a coordinator object that you can mock in, then assert that the mock’s version of ‘present:animated:’ gets called as you would expect.