TestCase : SwiftHTTP library not making the HTTP call
Asked Answered
T

1

4

Important Fact

I forgot to mention an important factor in the question. I am running this in a TestCase. I think this issue has something to do with the TestCase not awaiting for async completionHandler to return

Migrated out from Alamofire to SwiftHTTP, since I found this much easier.

On SwiftHHTP there is no way to know what URL got generated, what error it returned. For example, I tried to see the opt.debugDescription variable, it returned something cryptic like description String "<SwiftHTTP.HTTP: 0x60000007e540>"

Steps I have followed

  • I have set YES to Allow Arbitrary Loads.
  • Safari on the iPhone Simulator responds with the correct JSON if I paste fullurl ->http://120.0.0.1:8080/myapi/Driver/getDriver?driver=2243&domain=4345&key=asdfasdf. Even catalina.out on the tomcat server running on my mac responds with a debug message.

But when I run this in a test case under Xcode the below code prints none of debug print's.

  • --1->, --2-->, --3-->, nothing got printed.
  • Debugger breakpoints also dont stop here.

CODE

var getData = [String:String]()
       getData = ["domain": "4345",
           "driver" : "2343",
           "key" : "asdfasdf"]

       var urlComponents = URLComponents(string: fullURL)!
       var queryItems = [URLQueryItem]()
       queryItems = self.getData.map{ URLQueryItem(name : $0.0, value : $0.1) }
       urlComponents.queryItems = queryItems
       print("fullurl ->"+(urlComponents.url)!.absoluteString)

       do {
           let opt = try HTTP.GET((urlComponents.url)!.absoluteString)
                      opt.start { response in
               if let err = response.error {
                   print("--1-> error: \(err.localizedDescription)")
                   return //also notify app of failure as needed
               }
               print("--2--> opt finished: \(response.description)")
               self.responseData = response
           }
       } catch let error {
           print("--3--> got an error creating the request: \(error)")
       }    

EDIT

Even after changing the code to https or http://www.google.com, same result.

let testComponents = URLComponents(string: "https://www.google.com")!
        URLSession.shared.dataTask(with: (testComponents.url)!, completionHandler: {
            (data, response, error) in
            if(error != nil){
                print("..1>..")
            }else{
                do{
                    print ("..2>.." )
                    let json = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String : AnyObject]
                    self.responseData = json

                }catch let error as NSError{
                    print("..3>..")
                }
            }
        }).resume()

EDIT 1 Tried from here @Vivek's answer.

callWebService(url: (urlComponents.url)!.absoluteString)
.
.
func callWebService(url : String) {
.
.
let callURL = URL.init(string: url)

Nothing got printed again, Error / JSON, nothing.

Trinitrobenzene answered 27/2, 2017 at 8:34 Comment(3)
See this github.com/daltoniam/SwiftHTTP. Hope your url is not accepting authentication.Plectognath
no, the url request is not even reaching the server. As you see none of the prints are printing tooTrinitrobenzene
setenv("CFNETWORK_DIAGNOSTICS", "3", 1); does not enable any extra log filesTrinitrobenzene
P
3

Yes, Unit Tests don't wait by default for the completionHandler to be called. If you call asynchronous functions in tests, you don't need to change the function's code, but the behavior of the test.

The solution: XCTestExpectation

In your test-class (the subclass of XCTest), add this property:

var expectation: XCTestExpectation?

A test-function for an asynchronous request could basically look like this:

func testRequest() {
    expectation = expectation(description: "Fetched sites") //1

    //2
    some.asyncStuffWithCompletionHandler() {
        someData in
        if someData == nil {
            XCTestFail("no data") //3
            return
        }

        //looks like the request was successful
        expectation?.fulfill() //4
    }

    //5
    waitForExpectations(timeout: 30, handler: nil)
}

Explanation

  1. This defines, what you expect the tested code to do. But actually, it's not important, what you add as description. It's just an information for you, when running the test

  2. This is the function with a completionHandler, you are calling

  3. If you want to let the test fail within the completionHanlder, call XCTestFail()

  4. If everything in the completionHandler worked as expected, fulfill the expectation by calling expectation?.fulfill.

  5. Here comes the important part: This part of the code will be executed before the completionHandler! If this would be the end of the function, the test would be stopped. That's why we tell the test to wait until the expectations are fulfilled (or a certain amount of time passed)


There is an interesting blog post about Unit Tests. (see the section "XCTestExpectation") It's written in an old Swift syntax, but the concept is the same.

Playful answered 27/2, 2017 at 15:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.