cyclingIsBetter
cyclingIsBetter

Reputation: 17591

iOS: Unit test with a void func in Swift

I want to test this method that doesn't return a value but I want to check if works fine. Can you give me some suggestions?

func login() {

            if Utility.feature.isAvailable(myFeat) {
                if self.helper.ifAlreadyRed() {
                    self.showWebViewController()
                } else {
                    let firstVC = FirstViewController()
                    self.setRootController(firstVC)
                }
            } else {
                let secondVC = SecondViewController()
                self.setRootController(secondVC)
            }
    }

so what's the best approach to apply unit test here?

Upvotes: 8

Views: 2749

Answers (1)

nhgrif
nhgrif

Reputation: 62062

Testing side effects is one approach. But for an example like the code in question, I actually prefer a subclass-and-expect approach.

Your code has three different paths.

  1. If feature is available and already red, show web view controller.
  2. If feature is available and not already red, show first view controller.
  3. If feature is not available, show second view controller.

So assuming this login() function is part of FooViewController, one possibility is writing tests that follow this format:

func testLoginFeatureAvailableAndNotAlreadyRed() {

    class TestVC: FooViewController {
        let setRootExpectation: XCTExpectation

        init(expectation: XCTExpectation) {
            setRootExpectation = expectation
            super.init()
        }

        override func setRootController(vc: UIViewController) {
            defer { setRootExpectation.fulfill() }

            XCTAssertTrue(vc is FirstViewController)

            // TODO: Any other assertions on vc as appropriate

            // Note the lack of calling super here.  
            // Calling super would inaccurately conflate our code coverage reports
            // We're not actually asserting anything within the 
            // super implementation works as intended in this test
        }

        override func showWebViewController() {
            XCTFail("Followed wrong path.")
        }
    }

    let expectation = expectationWithDescription("Login present VC")

    let testVC = TestVC(expectation: expectation)
    testVC.loadView()
    testVC.viewDidLoad()

    // TODO: Set the state of testVC to whatever it should be
    // to expect the path we set our mock class to expect

    testVC.login()

    waitForExpectationsWithTimeout(0, handler: nil)

}

Upvotes: 5

Related Questions