【问题标题】:I have been trying to write the Unit test cases in swift for making an API call but not able to figure out how to write我一直在尝试快速编写单元测试用例以进行 API 调用,但无法弄清楚如何编写
【发布时间】:2022-10-06 16:26:33
【问题描述】:

我一直在尝试快速编写单元测试用例来进行 API 调用,但是在这方面是新手,我无法弄清楚如何编写相同的单元测试用例。这是我要为其编写单元测试用例的代码

class QuotesModel: ObservableObject {
    
    @Published var quotes = [Quote]()

    @MainActor  
    func fetchData() async {
        guard let url = URL(string: \"https://breakingbadapi.com/api/quotes\") else {
            print(\"Invalid URL\")
            return
        }
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            quotes = try JSONDecoder().decode([Quote].self, from: data)
        } catch {
            print(error)
        }
//        print(quotes)
    }
 
} 

我一直在尝试为此编写单元测试用例,但无法弄清楚我该怎么做。有人可以帮我弄这个吗?

  • 将解码分解为一个单独的函数并为该部分编写一个测试。您不应该尝试对 URLSession 进行单元测试。这样,您还可以获得更好的逻辑分离。

标签: swift mvvm xctest xctestcase


【解决方案1】:

URLSession.shared 是一个单身人士。使用单例没有任何问题。但是如果你直接使用它们,你就会放弃对依赖项的控制。而URLSession 是一种“尴尬的依赖”,它使测试变得更加困难。

所以改变你的代码,使它在生产时使用URLSession.shared,但在测试期间使用其他东西——你的测试可以控制的东西。让我们介绍一个协议,正如我在https://qualitycoding.org/swift-mocking/ 中描述的那样

protocol URLSessionProtocol {
    // We will add more here
}

使用扩展使 URLSession 符合这个新协议:

extension URLSession: URLSessionProtocol {}

更改您的生产代码以使用此协议的实例,而不是直接调用URLSession.shared。但提供URLSession.shared 作为默认值。例如,我们可以为您的方法添加一个参数:

func fetchData(urlSession: URLSessionProtocol = URLSession.shared) async { … }

为了能够使用urlSession,该协议需要您使用的URLSession 方法:

protocol URLSessionProtocol {
    func data(from url: URL) async throws -> (Data, URLResponse)
}

这样,您的调用代码将如下所示

let (data, _) = try await urlSession.data(from: url)

现在测试代码可以提供一个不同的实现来记录它是如何被调用的,并返回测试控制的预设数据。

【讨论】:

    猜你喜欢
    • 2022-11-14
    • 1970-01-01
    • 2019-03-16
    • 2018-02-11
    • 1970-01-01
    • 1970-01-01
    • 2019-02-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多