Skip to content

Instantly share code, notes, and snippets.

@yutailang0119
Last active May 31, 2020 07:40
Show Gist options
  • Save yutailang0119/c75ae0f15b0e5040c1c6c5b86c6bc77a to your computer and use it in GitHub Desktop.
Save yutailang0119/c75ae0f15b0e5040c1c6c5b86c6bc77a to your computer and use it in GitHub Desktop.
Mock Swift APIClient with Combine
@available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, macCatalyst 13.0, *)
// MARK: - Request
protocol Request {
associatedtype Response: Decodable
var urlRequest: URLRequest { get }
}
// MARK: - APISession
public protocol APISession {
func dataTaskPublisher<R: Request>(for request: R) -> AnyPublisher<(data: Data, response: URLResponse), URLError>
}
public protocol APISession {
func dataTaskPublisher<R: Request>(for request: R) -> AnyPublisher<(data: Data, response: URLResponse), URLError>
}
// MARK: - APIClient
protocol APIClient {
associatedtype Session: APISession
var session: Session { get }
func request<R: Request>(of request: R) -> AnyPublisher<R.Response, Error>
}
public extension APIClient {
func request<R: Request>(of request: R) -> AnyPublisher<R.Response, Error> {
session
.dataTaskPublisher(for: request)
.tryMap { data, response in
// something
}
.eraseToAnyPublisher()
}
}
// MARK: - Mock
class MockAPIClient: APIClient {
let session = MockAPISession()
}
class MockAPISession: APISession {
func dataTaskPublisher<R: Request>(for request: R) -> AnyPublisher<(data: Data, response: URLResponse), URLError> {
MockDataTaskPublisher(request: request)
.eraseToAnyPublisher()
}
}
struct MockDataTaskPublisher<R: Request>: Publisher {
typealias Output = (data: Data, response: URLResponse)
typealias Failure = URLError
let request: R
func receive<S>(subscriber: S) where S : Subscriber, Self.Failure == S.Failure, Self.Output == S.Input {
// something
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment