Skip to content

Instantly share code, notes, and snippets.

@GRGBISHOW
Last active March 21, 2024 05:24
Show Gist options
  • Save GRGBISHOW/284becb6f5ddd4bdb5965e473604efd0 to your computer and use it in GitHub Desktop.
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…
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