skip to Main Content

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


  1. What you want is to do UITest and not UnitTest.

    What is a Unit Test? https://x-team.com/blog/how-to-get-started-with-ios-unit-tests-in-swift/

    A unit test is a function you write that tests something about your
    app. A good unit test is small. It tests just one thing in isolation.
    For example, if your app adds up the total amount of time your user
    spent doing something, you might write a test to check if this total
    is correct.


    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:

    XCTAssert(app.staticTexts["Some Static String From SuppliersInvoiceController "].exists)
    
    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search