From 8eb76715a1a4a7cabc56a17c0d44bc6bb9d2ebcf Mon Sep 17 00:00:00 2001 From: Artem Zinnatullin Date: Sat, 10 Oct 2015 19:44:55 +0300 Subject: [PATCH] Add Single.doAfterTerminate() --- src/main/java/rx/Single.java | 22 ++++++++++++++ src/test/java/rx/SingleTest.java | 52 +++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/main/java/rx/Single.java b/src/main/java/rx/Single.java index b577f9a812..3880da9b0c 100644 --- a/src/main/java/rx/Single.java +++ b/src/main/java/rx/Single.java @@ -36,6 +36,7 @@ import rx.internal.operators.OperatorDelay; import rx.internal.operators.OperatorDoOnEach; import rx.internal.operators.OperatorDoOnUnsubscribe; +import rx.internal.operators.OperatorFinally; import rx.internal.operators.OperatorMap; import rx.internal.operators.OperatorObserveOn; import rx.internal.operators.OperatorOnErrorReturn; @@ -2020,4 +2021,25 @@ public void call(SingleSubscriber singleSubscriber) { public final Single doOnUnsubscribe(final Action0 action) { return lift(new OperatorDoOnUnsubscribe(action)); } + + /** + * Registers an {@link Action0} to be called when this {@link Single} invokes either + * {@link SingleSubscriber#onSuccess(Object)} onSuccess} or {@link SingleSubscriber#onError onError}. + *

+ * + *

+ *
Scheduler:
+ *
{@code doAfterTerminate} does not operate by default on a particular {@link Scheduler}.
+ *
+ * + * @param action + * an {@link Action0} to be invoked when the source {@link Single} finishes. + * @return a {@link Single} that emits the same item or error as the source {@link Single}, then invokes the + * {@link Action0} + * @see ReactiveX operators documentation: Do + */ + @Experimental + public final Single doAfterTerminate(Action0 action) { + return lift(new OperatorFinally(action)); + } } diff --git a/src/test/java/rx/SingleTest.java b/src/test/java/rx/SingleTest.java index 0fa8750709..17e3367835 100644 --- a/src/test/java/rx/SingleTest.java +++ b/src/test/java/rx/SingleTest.java @@ -51,7 +51,6 @@ import rx.schedulers.Schedulers; import rx.subscriptions.Subscriptions; - public class SingleTest { @Test @@ -891,4 +890,55 @@ public void call(SingleSubscriber singleSubscriber) { testSubscriber.assertNoValues(); testSubscriber.assertNoTerminalEvent(); } + + @Test + public void doAfterTerminateActionShouldBeInvokedAfterOnSuccess() { + Action0 action = mock(Action0.class); + + TestSubscriber testSubscriber = new TestSubscriber(); + + Single + .just("value") + .doAfterTerminate(action) + .subscribe(testSubscriber); + + testSubscriber.assertValue("value"); + testSubscriber.assertNoErrors(); + + verify(action).call(); + } + + @Test + public void doAfterTerminateActionShouldBeInvokedAfterOnError() { + Action0 action = mock(Action0.class); + + TestSubscriber testSubscriber = new TestSubscriber(); + + Throwable error = new IllegalStateException(); + + Single + .error(error) + .doAfterTerminate(action) + .subscribe(testSubscriber); + + testSubscriber.assertNoValues(); + testSubscriber.assertError(error); + + verify(action).call(); + } + + @Test + public void doAfterTerminateActionShouldNotBeInvokedUntilSubscriberSubscribes() { + Action0 action = mock(Action0.class); + + Single + .just("value") + .doAfterTerminate(action); + + Single + .error(new IllegalStateException()) + .doAfterTerminate(action); + + verifyZeroInteractions(action); + } }