Ways to Load UIViewController in a Unit Test

There are different ways to load UIViewController in a Unit Test and in this tutorial you will learn three of them.

  • Loading UIViewController from Main.storyboard,
  • Loading UIViewController from XIB,
  • Loading UIViewController that is not on the Main.storyboard and does have an interface XIB file. This is a type of UIViewController that creates views programmatically.

If you are interested in video lessons on how to write Unit tests and UI tests to test your Swift mobile app, check out this page: Unit Testing Swift Mobile App

Loading UIViewController from Main.storyboard

Let’s begin with a UIViewController that is instantiated from the Main.storyboard using Storyboard ID.  The steps to load this type of view controller in a Unit Test are very similar to how we load it in a regular Swift class.

  1. Create an instance of UIStoryboard,
  2. Call the instantiateViewController(withIdentifier identifier: String) method on the storyboard object to instantiate the view controller,
  3. This last step is unique to a Unit test. Call the loadViewIfNeeded() methodto load the view controller’s view if it has not yet been loaded. Once the view is loaded, it will make the viewDidLoad() method execute in a UIViewController class.
import XCTest
@testable import LoadingViewControllers

class LoadingViewControllersTests: XCTestCase {
    var sut: SignupViewController!
    
    override func setUpWithError() throws {
        // Step 1. Create an instance of UIStoryboard
        let storyboard = UIStoryboard(name: "Main", bundle: nil)

        // Step 2. Instantiate UIViewController with Storyboard ID
        sut = storyboard.instantiateViewController(withIdentifier: "SignupViewController") as? SignupViewController
        
        // Step 3. Make the viewDidLoad() execute.
        sut.loadViewIfNeeded()          
    }
    
    override func tearDownWithError() throws {
        sut = nil
    }
    
   // TEST METHODS BELOW

}

Loading UIViewController with XIB

To make your Unit Test load the UIViewController that has an interface XIB file is even easier.

  • Create an instance on UIViewController that uses XIB file. Make sure though that the view controller and the XIB files have the same names.
  • Call the loadViewIfNeeded() method to make the viewDidLoad() execute.
import XCTest
@testable import LoadingViewControllers

class LoadingViewControllerFromXIB: XCTestCase {
    var sut: LoginViewController!
    
    override func setUpWithError() throws {
        sut = LoginViewController()
        sut.loadViewIfNeeded()
    }

    override func tearDownWithError() throws {
        sut = nil
    }
    
   // TEST METHODS GO BELOW
 
}

UIViewController with No Storyboard or XIB File

To make our XCTest load the view controller that does not have any storyboard or XIB file is also easy. Although there a few details on how the controller class is created.

  1. The UIViewController will need to have an initializer that calls super.init(nibName: nil, bundle: nil),
  2. And the UIViewController will need to implement the required init?(coder: NSCoder) 

Below is an example of UIViewController that is now loaded from Main.storyboard and does not have XIB file.

import UIKit

class MainPageViewController: UIViewController {
 
    init() {
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
      
    override func viewDidLoad() {
        super.viewDidLoad()
 
        print("Main page view controller has loaded")
    }
 
}

To l0ad the above view controller in a unit test method all new need to do is:

  • Create an instance on UIViewController,
  • Call the loadViewIfNeeded() method to make the viewDidLoad() execute.
import XCTest
@testable import LoadingViewControllers

class LoadingHomePageViewController: XCTestCase {
    var sut: MainPageViewController!
    
    override func setUpWithError() throws {
        
        sut = MainPageViewController()
        sut.loadViewIfNeeded()
    }
    override func tearDownWithError() throws {
        sut = nil
    }

    // TEST METHODS BELOW
}

I hope this short tutorial was helpful to you. If you are interested to learn more about Unit testing and UI Testing of your Swift mobile application, then have a look at my video lessons here – “Unit Testing Swift Mobile App“.

Happy Unit Testing! 🙋🏻‍♂️

 

Leave a Reply

Your email address will not be published. Required fields are marked *