swift - 如何模拟DataTaskPublisher?

标签 swift unit-testing combine

我正在尝试使用 URLSession.DataTaskPublisher 为我的 API 编写一些单元测试。我在 Stackoverflow 上发现了一个已经存在的问题,但我正在努力使用建议的解决方案来实现一个工作类。

这是现有的问题:How to mock URLSession.DataTaskPublisher

protocol APIDataTaskPublisher {
    func dataTaskPublisher(for request: URLRequest) -> URLSession.DataTaskPublisher
}

class APISessionDataTaskPublisher: APIDataTaskPublisher {
    func dataTaskPublisher(for request: URLRequest) -> URLSession.DataTaskPublisher {
        return session.dataTaskPublisher(for: request)
    }

    var session: URLSession

    init(session: URLSession = URLSession.shared) {
        self.session = session
    }
}

class URLSessionMock: APIDataTaskPublisher {
    func dataTaskPublisher(for request: URLRequest) -> URLSession.DataTaskPublisher {
        // How can I return a mocked URLSession.DataTaskPublisher here?
    }
}

我的 API 然后像这样使用上面的内容:

class MyAPI {
    /// Shared URL session
    private let urlSession: APIDataTaskPublisher

    init(urlSession: APIDataTaskPublisher = APISessionDataTaskPublisher(session: URLSession.shared)) {
        self.urlSession = urlSession
    }
}

我不知道如何实现 URLSessionMock.dataTaskPublisher()。

最佳答案

模拟 DataTaskPublisher 可能会更简单。您真的关心发布者是否是 DataTaskPublisher 吗?可能不会。您可能关心的是获得与 DataTaskPublisher 相同的 OutputFailure 类型。因此,更改您的 API 以仅指定:

protocol APIProvider {
    typealias APIResponse = URLSession.DataTaskPublisher.Output
    func apiResponse(for request: URLRequest) -> AnyPublisher<APIResponse, URLError>
}

使 URLSession 符合生产用途:

extension URLSession: APIProvider {
    func apiResponse(for request: URLRequest) -> AnyPublisher<APIResponse, URLError> {
        return dataTaskPublisher(for: request).eraseToAnyPublisher()
    }
}

然后您的模拟可以以任何方便的方式创建发布者。例如:

struct MockAPIProvider: APIProvider {
    func apiResponse(for request: URLRequest) -> AnyPublisher<APIResponse, URLError> {
        let response = HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: "HTTP/1.1", headerFields: nil)!
        let data = "Hello, world!".data(using: .utf8)!
        return Just((data: data, response: response))
            .setFailureType(to: URLError.self)
            .eraseToAnyPublisher()
    }
}

关于swift - 如何模拟DataTaskPublisher?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60089803/

相关文章:

unit-testing - 稍后编写单元测试

unit-testing - 如何在Dart中测试异步Stream

scenekit - SwiftUI + Scenekit + 组合 + GeometryReader ==> 可滚动的 3D 模型列表 + 通过滚动列表旋转 3D 模型

Swift 组合链接 .mapError()

ios - 找不到带有 Cocoapods 0.37、Swift、框架的 GoogleAnalytics-iOS-SDK 的 header

ios - 类级别变量设置为什么总是为零?

javascript - Mocha/Chai 异步测试 'done()' fn 不工作

ios - Combine + SwiftUI 中的最佳数据绑定(bind)实践?

ios - 向 NavigationItem 添加按钮

iOS -weak_library 和 -bitcode_bundle(Xcode 设置 ENABLE_BITCODE=YES)不能一起使用