Last active
March 21, 2024 05:24
-
-
Save GRGBISHOW/284becb6f5ddd4bdb5965e473604efd0 to your computer and use it in GitHub Desktop.
TestableSubscriber, ever wondered how to test the publisher? This is a simple solution to test the emitted values by any publisher in Test target without calling the actual subscriber inside business logic.The provided XCTest case demonstrates how to use this TestableSubscriber for testing by subscribing to a publisher and asserting values and c…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
final class TestableSubscriber<Input, Failure: Error>: Subscriber { | |
typealias Input = Input | |
typealias Failure = Failure | |
private var subscription: Subscription? | |
private var values: [Input] = [] | |
private var completion: Subscribers.Completion<Failure>? | |
private var demand: Subscribers.Demand { | |
didSet { subscription?.request(demand) } | |
} | |
init(demand: Subscribers.Demand = .unlimited) { | |
self.demand = demand | |
} | |
func receive(_ input: Input) -> Subscribers.Demand { | |
values.append(input) // Emitted Values | |
return demand | |
} | |
func receive(completion: Subscribers.Completion<Failure>) { | |
self.completion = completion | |
cancel() | |
} | |
func receive(subscription: Subscription) { | |
self.subscription = subscription | |
subscription.request(.unlimited) | |
} | |
func cancel() { | |
subscription?.cancel() | |
subscription = nil | |
} | |
var emittedValues: [Input] { | |
values | |
} | |
var completionState: Subscribers.Completion<Failure>? { | |
completion | |
} | |
} | |
// Extension for publisher to connect TestableSubscriber | |
extension Publisher { | |
func testableSubscriber() -> TestableSubscriber<Output, Failure> { | |
let testSubscriber = TestableSubscriber<Output,Failure>() | |
subscribe(testSubscriber) | |
return testSubscriber | |
} | |
} | |
// Usuage in Test target. | |
final class SomeViewModelTests: XCTestCase { | |
func testPublisher() { | |
let publisher = Just("Hello, World!") // Test with any publisher, e.g viewModel.someDataPublisher | |
let testableSubscriber = publisher.testableSubscriber() | |
XCTAssertEqual(testableSubscriber.emittedValues.last, "Hello, World!") | |
XCTAssertEqual(testableSubscriber.completionState, .finished) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment