RxJava2 delay an observable until another observable emits












1















This is for unit testing purposes, as I want to verify correct behavior for a function where two data sources may return in different orders. Currently in my unit test, I'm creating an Observable with dummy data and simply using the delay operator to add a delay of 10 milliseconds for the data source I want to return second. However, this seems a bit ugly and could become problematic as I have more and more tests.



Is there a way to have an Observable wait to emit until another Observable completes?



Edit: Here's an example of a unit test that I have



public void testNetworkReturningBeforeLocal() {
Item localItem = new Item("local");
Item remoteItem = new Item("remote");
when(mDatabaseMock.getItem(any())).thenReturn(Observable.just(localItem).delay(10, TimeUnit.MILLISECONDS);
when(mApiMock.getItem(any())).thenReturn(Observable.just(remoteItem));

TestObserver<Item> observer = new TestObserver<>();
mRepository.getItem("blah").subscribe(observer); // calls getItem from database and API

observer.awaitTerminalEvent();
observer.assertResult(remoteItem);
}


I'm using delay(10, TimeUnit.MILLISECONDS) on the observable returned by the database to simulate the network response arriving first. What I'd like to do is delay the database observable until the network observable completes.










share|improve this question




















  • 1





    I would suggest you use a TestScheduler and your observables use this scheduler. You will have to post a minimal test showing what you currently have for a more definitive answer. However it would seem that you can make this easier as all this is just to invoke subsequent behaviour, maybe you are trying to test too much at once - can you not refactor to just test the behaviours independently?

    – Mark Keen
    Nov 23 '18 at 1:22













  • A couple of ways with operators: delaySubscription, delay(selector), concatEager to name a few.

    – akarnokd
    Nov 23 '18 at 11:13











  • @MarkKeen I've added an example test case above

    – theasianpianist
    Nov 23 '18 at 22:27











  • @akarnokd none of those seem to work. DelaySubscription delays the subscription but not the emission of items, which is what I need. I'm already using delay and want to avoid specifying a specific time to wait. concatEager returns one observable, but these are two observables returning test data from two separate sources.

    – theasianpianist
    Nov 23 '18 at 22:32











  • I'm a little confused, it is quite feasible to assume that a network call would always be slower than returning a local persisted value? I'm not sure how valid this test is - are you trying to prove rxjava works? That said, for a solution, as stated you'll require a TestScheduler, and use that with the delay operator, then forward time by 10 seconds, then make your assertions, also I'd make use fromCallable instead of just in your mock return values - reactivex.io/RxJava/javadoc/io/reactivex/schedulers/… you may also find the amb operator useful here.

    – Mark Keen
    Nov 24 '18 at 0:22


















1















This is for unit testing purposes, as I want to verify correct behavior for a function where two data sources may return in different orders. Currently in my unit test, I'm creating an Observable with dummy data and simply using the delay operator to add a delay of 10 milliseconds for the data source I want to return second. However, this seems a bit ugly and could become problematic as I have more and more tests.



Is there a way to have an Observable wait to emit until another Observable completes?



Edit: Here's an example of a unit test that I have



public void testNetworkReturningBeforeLocal() {
Item localItem = new Item("local");
Item remoteItem = new Item("remote");
when(mDatabaseMock.getItem(any())).thenReturn(Observable.just(localItem).delay(10, TimeUnit.MILLISECONDS);
when(mApiMock.getItem(any())).thenReturn(Observable.just(remoteItem));

TestObserver<Item> observer = new TestObserver<>();
mRepository.getItem("blah").subscribe(observer); // calls getItem from database and API

observer.awaitTerminalEvent();
observer.assertResult(remoteItem);
}


I'm using delay(10, TimeUnit.MILLISECONDS) on the observable returned by the database to simulate the network response arriving first. What I'd like to do is delay the database observable until the network observable completes.










share|improve this question




















  • 1





    I would suggest you use a TestScheduler and your observables use this scheduler. You will have to post a minimal test showing what you currently have for a more definitive answer. However it would seem that you can make this easier as all this is just to invoke subsequent behaviour, maybe you are trying to test too much at once - can you not refactor to just test the behaviours independently?

    – Mark Keen
    Nov 23 '18 at 1:22













  • A couple of ways with operators: delaySubscription, delay(selector), concatEager to name a few.

    – akarnokd
    Nov 23 '18 at 11:13











  • @MarkKeen I've added an example test case above

    – theasianpianist
    Nov 23 '18 at 22:27











  • @akarnokd none of those seem to work. DelaySubscription delays the subscription but not the emission of items, which is what I need. I'm already using delay and want to avoid specifying a specific time to wait. concatEager returns one observable, but these are two observables returning test data from two separate sources.

    – theasianpianist
    Nov 23 '18 at 22:32











  • I'm a little confused, it is quite feasible to assume that a network call would always be slower than returning a local persisted value? I'm not sure how valid this test is - are you trying to prove rxjava works? That said, for a solution, as stated you'll require a TestScheduler, and use that with the delay operator, then forward time by 10 seconds, then make your assertions, also I'd make use fromCallable instead of just in your mock return values - reactivex.io/RxJava/javadoc/io/reactivex/schedulers/… you may also find the amb operator useful here.

    – Mark Keen
    Nov 24 '18 at 0:22
















1












1








1








This is for unit testing purposes, as I want to verify correct behavior for a function where two data sources may return in different orders. Currently in my unit test, I'm creating an Observable with dummy data and simply using the delay operator to add a delay of 10 milliseconds for the data source I want to return second. However, this seems a bit ugly and could become problematic as I have more and more tests.



Is there a way to have an Observable wait to emit until another Observable completes?



Edit: Here's an example of a unit test that I have



public void testNetworkReturningBeforeLocal() {
Item localItem = new Item("local");
Item remoteItem = new Item("remote");
when(mDatabaseMock.getItem(any())).thenReturn(Observable.just(localItem).delay(10, TimeUnit.MILLISECONDS);
when(mApiMock.getItem(any())).thenReturn(Observable.just(remoteItem));

TestObserver<Item> observer = new TestObserver<>();
mRepository.getItem("blah").subscribe(observer); // calls getItem from database and API

observer.awaitTerminalEvent();
observer.assertResult(remoteItem);
}


I'm using delay(10, TimeUnit.MILLISECONDS) on the observable returned by the database to simulate the network response arriving first. What I'd like to do is delay the database observable until the network observable completes.










share|improve this question
















This is for unit testing purposes, as I want to verify correct behavior for a function where two data sources may return in different orders. Currently in my unit test, I'm creating an Observable with dummy data and simply using the delay operator to add a delay of 10 milliseconds for the data source I want to return second. However, this seems a bit ugly and could become problematic as I have more and more tests.



Is there a way to have an Observable wait to emit until another Observable completes?



Edit: Here's an example of a unit test that I have



public void testNetworkReturningBeforeLocal() {
Item localItem = new Item("local");
Item remoteItem = new Item("remote");
when(mDatabaseMock.getItem(any())).thenReturn(Observable.just(localItem).delay(10, TimeUnit.MILLISECONDS);
when(mApiMock.getItem(any())).thenReturn(Observable.just(remoteItem));

TestObserver<Item> observer = new TestObserver<>();
mRepository.getItem("blah").subscribe(observer); // calls getItem from database and API

observer.awaitTerminalEvent();
observer.assertResult(remoteItem);
}


I'm using delay(10, TimeUnit.MILLISECONDS) on the observable returned by the database to simulate the network response arriving first. What I'd like to do is delay the database observable until the network observable completes.







observable delay rx-java2






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 23 '18 at 22:24







theasianpianist

















asked Nov 22 '18 at 20:54









theasianpianisttheasianpianist

8819




8819








  • 1





    I would suggest you use a TestScheduler and your observables use this scheduler. You will have to post a minimal test showing what you currently have for a more definitive answer. However it would seem that you can make this easier as all this is just to invoke subsequent behaviour, maybe you are trying to test too much at once - can you not refactor to just test the behaviours independently?

    – Mark Keen
    Nov 23 '18 at 1:22













  • A couple of ways with operators: delaySubscription, delay(selector), concatEager to name a few.

    – akarnokd
    Nov 23 '18 at 11:13











  • @MarkKeen I've added an example test case above

    – theasianpianist
    Nov 23 '18 at 22:27











  • @akarnokd none of those seem to work. DelaySubscription delays the subscription but not the emission of items, which is what I need. I'm already using delay and want to avoid specifying a specific time to wait. concatEager returns one observable, but these are two observables returning test data from two separate sources.

    – theasianpianist
    Nov 23 '18 at 22:32











  • I'm a little confused, it is quite feasible to assume that a network call would always be slower than returning a local persisted value? I'm not sure how valid this test is - are you trying to prove rxjava works? That said, for a solution, as stated you'll require a TestScheduler, and use that with the delay operator, then forward time by 10 seconds, then make your assertions, also I'd make use fromCallable instead of just in your mock return values - reactivex.io/RxJava/javadoc/io/reactivex/schedulers/… you may also find the amb operator useful here.

    – Mark Keen
    Nov 24 '18 at 0:22
















  • 1





    I would suggest you use a TestScheduler and your observables use this scheduler. You will have to post a minimal test showing what you currently have for a more definitive answer. However it would seem that you can make this easier as all this is just to invoke subsequent behaviour, maybe you are trying to test too much at once - can you not refactor to just test the behaviours independently?

    – Mark Keen
    Nov 23 '18 at 1:22













  • A couple of ways with operators: delaySubscription, delay(selector), concatEager to name a few.

    – akarnokd
    Nov 23 '18 at 11:13











  • @MarkKeen I've added an example test case above

    – theasianpianist
    Nov 23 '18 at 22:27











  • @akarnokd none of those seem to work. DelaySubscription delays the subscription but not the emission of items, which is what I need. I'm already using delay and want to avoid specifying a specific time to wait. concatEager returns one observable, but these are two observables returning test data from two separate sources.

    – theasianpianist
    Nov 23 '18 at 22:32











  • I'm a little confused, it is quite feasible to assume that a network call would always be slower than returning a local persisted value? I'm not sure how valid this test is - are you trying to prove rxjava works? That said, for a solution, as stated you'll require a TestScheduler, and use that with the delay operator, then forward time by 10 seconds, then make your assertions, also I'd make use fromCallable instead of just in your mock return values - reactivex.io/RxJava/javadoc/io/reactivex/schedulers/… you may also find the amb operator useful here.

    – Mark Keen
    Nov 24 '18 at 0:22










1




1





I would suggest you use a TestScheduler and your observables use this scheduler. You will have to post a minimal test showing what you currently have for a more definitive answer. However it would seem that you can make this easier as all this is just to invoke subsequent behaviour, maybe you are trying to test too much at once - can you not refactor to just test the behaviours independently?

– Mark Keen
Nov 23 '18 at 1:22







I would suggest you use a TestScheduler and your observables use this scheduler. You will have to post a minimal test showing what you currently have for a more definitive answer. However it would seem that you can make this easier as all this is just to invoke subsequent behaviour, maybe you are trying to test too much at once - can you not refactor to just test the behaviours independently?

– Mark Keen
Nov 23 '18 at 1:22















A couple of ways with operators: delaySubscription, delay(selector), concatEager to name a few.

– akarnokd
Nov 23 '18 at 11:13





A couple of ways with operators: delaySubscription, delay(selector), concatEager to name a few.

– akarnokd
Nov 23 '18 at 11:13













@MarkKeen I've added an example test case above

– theasianpianist
Nov 23 '18 at 22:27





@MarkKeen I've added an example test case above

– theasianpianist
Nov 23 '18 at 22:27













@akarnokd none of those seem to work. DelaySubscription delays the subscription but not the emission of items, which is what I need. I'm already using delay and want to avoid specifying a specific time to wait. concatEager returns one observable, but these are two observables returning test data from two separate sources.

– theasianpianist
Nov 23 '18 at 22:32





@akarnokd none of those seem to work. DelaySubscription delays the subscription but not the emission of items, which is what I need. I'm already using delay and want to avoid specifying a specific time to wait. concatEager returns one observable, but these are two observables returning test data from two separate sources.

– theasianpianist
Nov 23 '18 at 22:32













I'm a little confused, it is quite feasible to assume that a network call would always be slower than returning a local persisted value? I'm not sure how valid this test is - are you trying to prove rxjava works? That said, for a solution, as stated you'll require a TestScheduler, and use that with the delay operator, then forward time by 10 seconds, then make your assertions, also I'd make use fromCallable instead of just in your mock return values - reactivex.io/RxJava/javadoc/io/reactivex/schedulers/… you may also find the amb operator useful here.

– Mark Keen
Nov 24 '18 at 0:22







I'm a little confused, it is quite feasible to assume that a network call would always be slower than returning a local persisted value? I'm not sure how valid this test is - are you trying to prove rxjava works? That said, for a solution, as stated you'll require a TestScheduler, and use that with the delay operator, then forward time by 10 seconds, then make your assertions, also I'd make use fromCallable instead of just in your mock return values - reactivex.io/RxJava/javadoc/io/reactivex/schedulers/… you may also find the amb operator useful here.

– Mark Keen
Nov 24 '18 at 0:22














0






active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53437873%2frxjava2-delay-an-observable-until-another-observable-emits%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes
















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53437873%2frxjava2-delay-an-observable-until-another-observable-emits%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

Xamarin.form Move up view when keyboard appear

Post-Redirect-Get with Spring WebFlux and Thymeleaf

Anylogic : not able to use stopDelay()