Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing a method that uses REST calls in Swift

Let me start out by stating I'm still unfamiliar with what I'm trying to do, but striving to get better!

I'm working on a project that I'm writing unit tests for and I'm having some trouble with how to approach the problem.

The method I'm testing utilizes a RESTAPI call to verify a users credentials. I'm not sure what the best way to unit test would be.

Here is the method I'm looking to make the Unit test for:

@IBAction func loginBtnActivate(sender: UIButton) {
    let enteredEmail: String = emailField.text!
    let enteredPassword: String = passwordField.text!
    let testInfo:[String: AnyObject] = ["User": enteredEmail, "Password": enteredPassword]
    RestApiManager.sharedInstance.postLogin(testInfo) { (json, statusCode) in
        if statusCode == 200 {
            let AuthToken: TokenObject = (TokenObject(json: json))
            try! self.keychain.set(AuthToken.Authorization, key:"Authorization")
            try! self.keychain.set(AuthToken.LifeTime, key: "LifeTime")
            try! self.keychain.set(AuthToken.UUID, key: "UUID")
             NSOperationQueue.mainQueue().addOperationWithBlock {
                self.performSegueWithIdentifier("loginToMyHealth", sender: nil)
            }
        } else if statusCode == 401 {
            self.incorrectLoginAlert()
        } else if statusCode == 503 {
            print("Service Unavailable Please Try Again Later")
        }
    }
}

This is currently the approach I'm taking:

 func testLoginInfoMatchesDataOnServer(){
    let enteredEmail: String = "user"
    let enteredPassword: String = "password"
    let testInfo:[String: AnyObject] = ["User": enteredEmail, "Password": enteredPassword]
    RestApiManager.sharedInstance.postLogin(testInfo) { (json, statusCode) in
    XCTAssert(statusCode == 200, "statusCode is not matching the server data")
}

I'm simply verifying that the Rest call is successful and that the credentials are matching the JSON. The XCTAssert call doesn't appear to be working correctly. No matter what I put as the first parameter, XCTAssert doesn't affect whether the test is successful or not.

Example, if I put:

XCTAssert(false, "statusCode is not matching the server data")

The test will still pass regardless of what I put. If I place the Assert function outside the brackets then it appears the variable "statusCode" is out of scope so I'm stuck with a

Use of unresolved identifier 'statusCode'.

   func testLoginInfoMatchesDataOnServer(){
let enteredEmail: String = "user"
let enteredPassword: String = "password"
let testInfo:[String: AnyObject] = ["User": enteredEmail, "Password": enteredPassword]
RestApiManager.sharedInstance.postLogin(testInfo) { (json, statusCode) in
}
XCTAssert(statusCode == 200, "statusCode is not matching the server data")
}

I was looking at this guide for help.. Would this be a better approach for what I'm trying to do?

http://roadfiresoftware.com/2016/06/how-do-you-unit-test-rest-calls-in-swift/

Again my understanding of some core concepts might be entirely off so I really appreciate your advice here!

Thanks in advance!

Sean W.

like image 549
Sean Weiss Avatar asked Feb 06 '23 02:02

Sean Weiss


1 Answers

First Few problems with your code

function test(){    
    RestApiManager.sharedInstance.postLogin(testInfo) { (json, statusCode) in

    }//PostLogin call ends
    XCTAssert(statusCode == 200, "statusCode is not matching the server data") // Here StatusCode is not accessible as outside the block
}// end function

If you want to use Status Code you should do

function test(){    
    RestApiManager.sharedInstance.postLogin(testInfo) { (json, statusCode) in
        XCTAssert(statusCode == 200, "statusCode is not matching the server data") // Here StatusCode is accessible inside the block
    }//PostLogin call ends
}// end function

But this will fail since you need to wait for the response. That can be done using

waitForExpectationsWithTimeout(5)

So proper way to call this would be --

function test(){    
    let URL = NSURL(string: "http://google.com/")!
    let expectation = expectationWithDescription("GET \(URL)")
    RestApiManager.sharedInstance.postLogin(testInfo) { (json, statusCode) in
        XCTAssert(statusCode == 200, "statusCode is not matching the server data") // Here StatusCode is accessible inside the block
        expectation.fulfill()
    }//PostLogin call ends
    waitForExpectationsWithTimeout(5){ error in 
        if let error = error {
            print("Error: \(error.localizedDescription)")
        }
    }//Wait block end
}// end function

Important lines here are

expectation.fulfill() // tells process is complete

and

waitForExpectationsWithTimeout(5){} //tells wait for 5secs or throw error

For more info

like image 178
katch Avatar answered Feb 16 '23 09:02

katch