1

Thanks in advance for any advice!

I'm setting up some unit tests in swift for iOS development. The method requires a call to the keychain to create an authToken to successfully run the function. I'm not sure how to approach creating a unit test for this kind of environment. Do I mock up a local file that I can use to bypass the authentication? Do I try to skip the authentication step entirely?

The function I'm testing is a private function as well and I'm having a hard time conceptualizing how I can test it through the public methods. Here is the code I'm working with:

override func viewDidLoad() {
    super.viewDidLoad()
    self.setMyDoctorsNavBarTitle()
    self.setBackgroundWaterMark()
    self.getDoctors()
    //self.refreshControl?.addTarget(self, action: #selector(MyDoctorsViewController.refresh(_:)), forControlEvents: UIControlEvents.ValueChanged)

}

private func getDoctors() {
    let authToken: [String: AnyObject] = [ "Authorization": keychain["Authorization"]!, // creates an authToken with the current values stored in
                                           "UUID": keychain["UUID"]!, "LifeTime": keychain["LifeTime"]! ] // the keychain

    RestApiManager.sharedInstance.postMyDocs(authToken) { (json, statusCode) in // passes the created authToken to postMyDocs in RestAPI to see if
        if statusCode == 200 {                                                                              // the token matches what's on the server
            if let results = json["Doctors"].array { // If the credentials pass, we grab the json file and create an array of Doctors
                for entry in results {
                    self.buildDoctorObject(entry) // Doctors information is parsed into individual objects
                }
            }
        } else if statusCode == 401 {
            /* If statucCode is 401, the user's AuthToken has expired. The historical AuthToken data will be removed from the iOS KeyChain and the user will be redirected to the login screen to reauthorize with the API 
            */
            self.keychain["Authorization"] = nil
            self.keychain["UUID"] = nil
            self.keychain["LifeTime"] = nil

            let loginController = self.storyboard?.instantiateViewControllerWithIdentifier("LoginViewController") as! LoginViewController

            NSOperationQueue.mainQueue().addOperationWithBlock {
                self.presentViewController(loginController, animated: true, completion: nil)
            }

        } else if statusCode == 503 {
            print("Service Unavailable Please Try Again Later")
        }

    }

}

private func buildDoctorObject(json: JSON){
    let fName = json["FirstName"].stringValue
    let lName = json["LastName"].stringValue
    let city = json["City"].stringValue
    let phNum = json["PhoneNumber"].stringValue
    let faxNum = json["FaxNumber"].stringValue
    let state = json["State"].stringValue
    let addr = json["Address"].stringValue
    let img = json["Image"].stringValue
    let zip = json["Zip"].stringValue
    let tax = json["Taxonomy"].stringValue

    let docObj = DoctorObject(fName: fName, lName: lName, addr: addr, city: city, state: state, zip: zip, phNum: phNum, faxNum: faxNum, img: img, tax: tax)

    self.docs.append(docObj)
    self.tableView.reloadData()
}

I want to be able to Unit Test the getDoctors() and buildDoctorObject() functions, but I can only do that indirectly through viewDidLoad() since they're private.

I want to be able to test that the statusCode is being brought down correctly from the server and the appropriate steps take place if it comes back as 200 or 401.

I'm not necessarily looking for complete code, but simply a way to approach the problem. If you know of resources that might be helpful I would be grateful. I'm very new to this and I tried looking into resources online but couldn't find anything. A lot of what I found was you don't want to test private functions directly, and isn't advised to change the functions to public for the sake of testing.

Thanks again for looking into it!

Sean W.

Sean Weiss
  • 63
  • 1
  • 5

1 Answers1

0

Define that private method in the Test Class, with the same signature. Just try to call that method it will call your actual class method.

Sachin Vas
  • 1,757
  • 12
  • 16
  • So essentially copy and paste that private method in the test class? There are some other methods that are required for the 2 I'm working on, am I essentially copying the whole viewcontroller into the test class? Thanks for the advice! – Sean Weiss Sep 29 '16 at 15:03