如何使用本地json文件对网络请求进行单元测试?

时间:2019-01-04 08:59:31

标签: ios swift unit-testing asynchronous networking

我正在尝试找出对网络请求进行单元测试的最佳方法。我最初的想法是使用JSON响应创建一个本地文件以进行测试,但这似乎不起作用。请参阅下面的代码。

我想测试我是否可以从下面的函数中的完成处理程序中获得非nil数组。

class APIClient {
    let downloader = JSONDownloader() // just a class that creates a new data task

    // what I want to test
    func getArticles(from url: URL?, completion: @escaping([Article]?, Error?) -> ()) {
        guard let url = url else { return }

        let request = URLRequest(url: url)
        let task = downloader.createTask(with: request) { json, error in
            DispatchQueue.main.async {

                // parse JSON
                ...

                completion(articles, nil)
            }
        }

        task.resume()
    }
}

我尝试如下所示进行测试,但无济于事。

func testArticleResponseIsNotNil() {
    let bundle = Bundle(for: APIClientTests.self)
    guard let path = Bundle.path(forResource: "response-articles", ofType: "json", inDirectory: bundle.bundlePath) else {
        XCTFail("Missing file: response-articles.json")
        return
    }

    let url = URL(fileURLWithPath: path)
    var articles: [Article]?

    let expectation = self.expectation(description: "Articles")
    let client = APIClient()
    client.getArticles(from: url) { response, error in
        articles = response
        expectation.fulfill()
    }

    wait(for: [expectation], timeout: 5)
    XCTAssertNotNil(articles)
}

关于我应该如何精确测试此功能的任何想法?

编辑:这是JSONDownloader类。

class JSONDownloader {

    let session: URLSession

    init(configuration: URLSessionConfiguration) {
        self.session = URLSession(configuration: configuration)
    }

    convenience init() {
        self.init(configuration: .default)
    }

    typealias JSON = [String: AnyObject]

    func createTask(with request: URLRequest, completion: @escaping(JSON?, Error?) -> ()) -> URLSessionDataTask {
        let task = session.dataTask(with: request) { data, response, error in
            guard let httpResponse = response as? HTTPURLResponse else { return }

            if httpResponse.statusCode == 200 {
                if let data = data {
                    do {
                        let json = try JSONSerialization.jsonObject(with: data, options: []) as? JSON
                        completion(json, nil)
                    } catch { completion(nil, error) }
                } else { completion(nil, error) }
            } else { completion(nil, error) }
        }

        return task
    }
}

0 个答案:

没有答案