Open
Description
Now RetryWhen subscribes to upstream twice. This is because the Sink itself subscribes to the upstream in .init.
Test testSuccessfulRetry() checks the number of subscriptions, but not correctly. It should check that the error publisher produces at least one item.
The correct test should look like this:
func testSuccessfulRetry() {
var times = 0
var retriesCount = 0
var expectedOutput: Int?
var completion: Subscribers.Completion<RetryWhenTests.MyError>?
subscription = Deferred(createPublisher: { () -> AnyPublisher<Int, MyError> in
defer { times += 1 }
if times == 0 {
return Fail<Int, MyError>(error: MyError.someError).eraseToAnyPublisher()
}
else {
return Just(5).setFailureType(to: MyError.self).eraseToAnyPublisher()
}
})
.retryWhen { error in
error
.handleEvents(receiveOutput: { _ in retriesCount += 1})
.map { _ in }
}
.sink(
receiveCompletion: { completion = $0 },
receiveValue: { expectedOutput = $0 }
)
XCTAssertEqual(
expectedOutput,
5
)
XCTAssertEqual(completion, .finished)
XCTAssertEqual(times, 2)
XCTAssertEqual(retriesCount, 1)
}
A possible solution is to remove upstream subscription from Sink.init and setting upstreamIsCancelled cancelUpstream function.
private let lock = NSRecursiveLock()
/// ...
func cancelUpstream() {
lock.lock()
guard !upstreamIsCancelled else {
lock.unlock()
return
}
upstreamIsCancelled = true
lock.unlock()
upstreamSubscription.kill()
}
Metadata
Metadata
Assignees
Labels
No labels