Ожидание нескольких асинхронных вызовов в setUp() XCTestCase

Мне нужно выполнить несколько звонков, прежде чем позволить test() метод запуска. У меня есть блок завершения, и я использую waitForExpectations(), Поскольку существует более одного асинхронного вызова, я использую счетчик. Я позволил expectation.fulfill() произойдет только тогда, когда счетчик достигнет количества звонков.

override func setUp() {
    super.setUp()

    let exp = expectation(description: "waitForSetUp")
    var counter = 0

    // Issue an async request
    self.addEventToCalendar(title: "Test1", description: "Description test1", startDate: NSDate().addingTimeInterval(-36000), endDate: NSDate()){(success, error) in
        if (success) && (error == nil) {
            counter = counter + 1
            if(counter == 2){exp.fulfill()}
        }
    }

    self.addEventToCalendar(title: "Test2", description: "Description test2", startDate: NSDate(), endDate: NSDate().addingTimeInterval(36000)){(success, error) in
        if (success) && (error == nil) {
            counter = counter + 1
            if(counter == 2){exp.fulfill()}
        }
    }

    waitForExpectations(timeout: 40, handler: nil)        
}

Эта конструкция не работает. test() Метод иногда запускается до возврата вызовов (не всегда).

Как я могу сделать setUp() ждать возвращения нескольких асинхронных вызовов?

1 ответ

Решение

У меня был похожий случай. В итоге я решил вызвать несколько функций, которые добавляют ожидания для моих предпосылок и устанавливают разумные значения времени ожидания ожидания. В обработчиках завершения ожиданий я запустил следующий шаг моего алгоритма установки. После того, как все предварительные шаги пройдены, я начинаю реальную логику тестирования.

Прикрепление ссылки на Apple Docs.

РЕДАКТИРОВАТЬ: Пожалуйста, смотрите пример кода ниже:

class CommonTests: XCTestCase {
    var validate: XCTestExpectation? = nil

    func testMytest() {        
      validate(completion: {
        loadSomeStuff(completion: { (list: [Stuff]?) in
          // actual test
        }
      })
    }

    func validate(completion: @escaping ()->()) {
        self.validateExpectation = self.expectation(description: "Setup")
        // async operation can be fired here
        // or if already started from somewhere else just wait for it to complete


        self.waitForExpectations(timeout: 60) { (error: Error?) in
            XCTAssert((error == nil), error?.localizedDescription ?? "Failed with unknown error")
            completion()
        }
    }

    func validateAsyncCompleted() {
      self.validateExpectation?.fulfill()
    }

    func loadStuff(completion: @escaping ([Stuff]?)->()) {

      // possible place for assertion or some other checks

      let expectation = self.expectation(description: "loading")
      DispatchQueue.global().async {

        let result: [Stuff]? = nil
        // load operation

        expectation.fulfill()
        completion(result)
      }

      self.waitForExpectations(timeout: 90) {  (error: Error?) in
        XCTAssert((error == nil), error?.localizedDescription ?? "load - failed with unknown error")
      }
    }
}

ПРИМЕЧАНИЕ. Существует два подхода к ожиданиям: первое ожидание сохраняется в переменной, поэтому при необходимости оно может быть выполнено из другой функции, другое создается локально в теле функции и выполняется из замыкания.

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