我正在尝试使用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吗?可能不会。您可能关心的是获得与oj​​it_code相同的OutputFailure类型。因此,将您的API更改为仅指定以下内容:

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

使其符合DataTaskPublisher以供生产使用:
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/

10-13 05:56