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)
}

объяснение

  1. Это определяет, что вы ожидаете от тестируемого кода. Но на самом деле, это не важно, что вы добавляете в качестве описания. Это просто информация для вас, при запуске теста

  2. Это функция с completionHandler, ты звонишь

  3. Если вы хотите, чтобы тест не прошел в completionHanlder, вызов XCTestFail()

  4. Если все в completionHandler работал как положено, выполни expectation позвонив expectation?.fulfill,

  5. Вот важная часть: эта часть кода будет выполнена до того, как completionHandler! Если это будет конец функции, тест будет остановлен. Вот почему мы говорим тесту подождать, пока ожидания не будут выполнены (или определенное количество времени прошло)


Есть интересное сообщение в блоге о модульных тестах. (см. раздел "XCTestExpectation"). Он написан в старом синтаксисе Swift, но концепция та же.

Другие вопросы по тегам