Unit Testing View Controllers


Hi guys, have anyone of you tried unit testing a view controller where a view controller needs to present something like alerts or a new view controller.

Currently I am trying to test if my view controller shows an alert after present an alert controller. But when I accessed the view controller’s isPresentingViewController, presentedViewController. It always return nil

Here’s my snippet code:

  func testForNoConnectionState() {
    let _ = createUsernameVC.view
    let observableExpectation = expectation(description: "Observable Expectation")
    createUsernameVC.viewModel.output.viewControllerState.asObservable().subscribe(onNext: { (state) in
      XCTAssertEqual(state, CreateUsernameViewControllerState.noConnection)
    }).disposed(by: disposeBag)
    XCTAssertEqual((createUsernameVC.presentedViewController as! UIAlertController).title, "No connection")
    XCTAssertEqual((createUsernameVC.presentedViewController as! UIAlertController).message, "Please connect to the internet")


This test fails by the way because presentedViewController always returns nil.


How did you present the View controller? About presentedViewController

If the current view controller did not present another view controller modally, the value in this property is nil .


I do not use the unit testing when it involves the UI. You may want to consider doing VC tests using the UI test framework.

My test is organized like below:
UI Tests - integration, UI tests, would use mock or real services
Unit Tests - not UI code and usually would use only fake/mocks


Haven’t tested this but you may need to add your view controller to a UIWindow:


beforeEach {
  let window = UIWindow(frame: UIScreen.main.bounds)
  window.rootViewController = vc
  _ = vc.view

It’s using Quick syntax but that’s basically you’re setUp() method on XCTest. For some UIView/UIViewController properties, you need to add them to a UIWindow before they work ex.(firstResponder: https://clean-swift.com/testing-view-controller-part-2/)

For me, I’m not sure about RXSwift testing (I’m sure there’s a specialized library for that )but I would just probably check a Mock that receives the no connection event for a unit test. and just assert the presented view controller on a UI test. Although that’s probably a more difficult set-up.


XCTAssert(ViewModelOutputMock.receivedNoConnectionEvent == true)