问题
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
toAllow 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
. Evencatalina.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.
回答1:
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
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
This is the function with a
completionHandler
, you are callingIf you want to let the test fail within the
completionHanlder
, callXCTestFail()
If everything in the
completionHandler
worked as expected, fulfill theexpectation
by callingexpectation?.fulfill
.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.
来源:https://stackoverflow.com/questions/42481033/testcase-swifthttp-library-not-making-the-http-call