我一直在尝试用swift编写单元测试用例来进行API调用,但不能弄清楚如何编写

qcbq4gxm  于 2022-12-26  发布在  Swift
关注(0)|答案(1)|浏览(117)

我一直在尝试编写单元测试用例在swift中进行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)
    }
 
}

我一直在尝试编写单元测试用例,但是不知道该怎么做。有人能帮我吗?

vc9ivgsu

vc9ivgsu1#

URLSession.shared是一个单例。使用单例并没有什么错。但是如果直接使用它们,您的依赖关系就会变成硬连接,您就会给予控制。而且URLSession是一个“笨拙的依赖关系”,会使测试更加困难。让我们替换它。
因此,更改您的代码,使其在生产中使用URLSession.shared,而在测试中使用其他东西-您的测试可以控制的东西。

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(for request: URLRequest, delegate: URLSessionTaskDelegate?) async throws -> (Data, URLResponse)
}

不幸的是,我们不能直接在协议中为delegate参数添加= nil默认值,解决这个问题的最简单方法是从调用代码显式传递它,现在看起来像

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

(We也可以向协议添加扩展)。
现在测试代码可以提供一个不同的实现来记录它是如何被调用的。(它被调用了多少次?你使用了正确的URL吗?)并且它返回由测试控制的固定数据。
......所有这些都是为了说:不要编写代码,并期望能够为它编写微测试,因为这是困难的。相反,塑造你的代码,使其易于编写微测试。

相关问题