TestCase: библиотека SwiftHTTP не выполняет HTTP-вызов
Важный факт
Я забыл упомянуть важный фактор в этом вопросе. Я запускаю это в TestCase. Я думаю, что эта проблема имеет отношение к TestCase, не ожидающему завершения асинхронного завершения.
Мигрировал из Alamofire
в SwiftHTTP
, поскольку я нашел это намного проще.
На SwiftHHTP нет способа узнать, какой URL был сгенерирован, какую ошибку он возвратил. Например, я пытался увидеть opt.debugDescription
переменная, она возвращает что-то загадочное, как описание String "<SwiftHTTP.HTTP: 0x60000007e540>"
Шаги, за которыми я следовал
- Я поставил
YES
вAllow Arbitrary Loads
, - Safari на iPhone Simulator отвечает правильным JSON, если я вставлю
fullurl ->http://120.0.0.1:8080/myapi/Driver/getDriver?driver=2243&domain=4345&key=asdfasdf
, Четноеcatalina.out
на сервере Tomcat, работающем на моем Mac, отвечает сообщением об отладке.
Но когда я запускаю это в тестовом случае под Xcode, приведенный ниже код не печатает ни один из отладочных отпечатков.
- --1->, --2 ->, --3 ->, ничего не напечатано.
- Точки останова отладчика также не останавливаются здесь.
КОД
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)")
}
РЕДАКТИРОВАТЬ
Даже после изменения кода на https
или же http://www.google.com
, тот же результат.
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()
РЕДАКТИРОВАТЬ 1 Попробовал отсюда @ ответ Вивека.
callWebService(url: (urlComponents.url)!.absoluteString)
.
.
func callWebService(url : String) {
.
.
let callURL = URL.init(string: url)
Ничего не было напечатано снова, Ошибка / JSON, ничего.
1 ответ
Да, модульные тесты не ждут по умолчанию completionHandler
быть названным. Если вы вызываете асинхронные функции в тестах, вам не нужно менять код функции, а нужно поведение теста.
Решение: XCTestExpectation
В вашем тестовом классе (подкласс XCTest
), добавьте это свойство:
var expectation: XCTestExpectation?
Тест-функция для асинхронного запроса может выглядеть примерно так:
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)
}
объяснение
Это определяет, что вы ожидаете от тестируемого кода. Но на самом деле, это не важно, что вы добавляете в качестве описания. Это просто информация для вас, при запуске теста
Это функция с
completionHandler
, ты звонишьЕсли вы хотите, чтобы тест не прошел в
completionHanlder
, вызовXCTestFail()
Если все в
completionHandler
работал как положено, выполниexpectation
позвонивexpectation?.fulfill
,Вот важная часть: эта часть кода будет выполнена до того, как
completionHandler
! Если это будет конец функции, тест будет остановлен. Вот почему мы говорим тесту подождать, пока ожидания не будут выполнены (или определенное количество времени прошло)
Есть интересное сообщение в блоге о модульных тестах. (см. раздел "XCTestExpectation"). Он написан в старом синтаксисе Swift, но концепция та же.