Как написать модульный тест для `downloadTask` с` завершением Handler `?

Вот моя функция загрузки:

// Download a file from the url to the local directory
class func downloadUrl(url: URL, to dirUrl: URL, completion: (() -> ())?){
    let sessionConfig = URLSessionConfiguration.default
    let session = URLSession(configuration: sessionConfig)
    let request = URLRequest(url: url)

    let task = session.downloadTask(with: request) {(tempLocalUrl, response, error) in
        if let tempLocalUrl = tempLocalUrl, error == nil {
            // Success, copy the downloaded file from the memory to the disk
            print("Finished downloading!")
            do {
                try FileManager.default.copyItem(at: tempLocalUrl,to:
                    dirUrl.appendingPathComponent((response?.suggestedFilename)!))
                if completion != nil {
                    completion!()
                }
            } catch (let writeError) {
                print("Fliled to write file \(dirUrl) : \(writeError)")
            }
        } else {
            print("Failure: \(String(describing: error?.localizedDescription))")
        }
    }
    task.resume()
}

Я хочу написать метод модульного теста, чтобы проверить, загружает ли он файл с url к dirUrl,

func testDownloadUrl(){
    let fm = FileManager.default
    let url = URL(string: "https://raw.githubusercontent.com/apple/swift/master/README.md")
    fileDownloader.downloadUrl(url: url!, to: fm.temporaryDirectory, completion: nil)

    // Check the contents of temp file
    let tempContents = try? fm.contentsOfDirectory(atPath: fm.temporaryDirectory.path)
        print("Contents: \(tempContents)")
    }

Тем не менее, не было никакого вывода "Закончена загрузка!" или "Сбой...", хотя я прошел модульное тестирование, поэтому я думаю, что в этом тесте не было вызвано завершение.

У меня вопрос, как заставить метод модульного теста ждать, пока задача загрузки не будет завершена?

1 ответ

Решение

Стандартная идиома заключается в использовании API асинхронного тестирования XCode, в основном XCTestExpectation учебный класс. Они доступны начиная с Xcode 6, поэтому, если вы используете последнюю версию, вы должны быть покрыты;)

Общий шаблон асинхронного теста выглядит следующим образом:

func testAsyncFunction() {
    let asyncDone = expectation(description: "Async function")
    ...
    someAsyncFunction(...) {
        ...
        asyncDone.fulfill()
    }
    wait(for: [asyncDone], timeout: 10)
    /* Test the results here */
}

Это заблокирует выполнение теста до тех пор, пока вышеупомянутая функция не завершится (или не истечет указанное время ожидания).

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