How should I use RxJava's TestScheduler
? I come from a .NET background but the TestScheduler
in RxJava does not seem to work the same way as the test scheduler in .NET rx.
Here is sample code that I want to test
Observable<Long> tick = Observable.interval(1, TimeUnit.SECONDS);
contactsRepository.find(index)
.buffer(MAX_CONTACTS_FETCH)
.zipWith(tick, new Func2<List<ContactDto>, Long, List<ContactDto>>() {
@Override
public List<ContactDto> call(List<ContactDto> contactList, Long aLong) {
return contactList;
}
}).subscribe()
I've tried:
subscribeOn(testScheduler)
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS);
testScheduler.triggerActions();
with no luck.
I made a little example of how to use a TestScheduler
. I think it's very similar to the .NET implementation
@Test
public void should_test_the_test_schedulers() {
TestScheduler scheduler = new TestScheduler();
final List<Long> result = new ArrayList<>();
Observable.interval(1, TimeUnit.SECONDS, scheduler)
.take(5)
.subscribe(result::add);
assertTrue(result.isEmpty());
scheduler.advanceTimeBy(2, TimeUnit.SECONDS);
assertEquals(2, result.size());
scheduler.advanceTimeBy(10, TimeUnit.SECONDS);
assertEquals(5, result.size());
}
https://github.com/bric3/demo-rxjava-humantalk/blob/master/src/test/java/demo/humantalk/rxjava/SchedulersTest.java
EDIT
According to your code : you should pass the scheduler to the Observable.interval
operation, as this is what you want to control :
TestScheduler scheduler = new TestScheduler();
Observable<Long> tick = Observable.interval(1, TimeUnit.SECONDS, scheduler);
Subscription toBeTested = Observable.from(Arrays.asList(1, 2, 3, 4, 5))
.buffer(3)
.zipWith(tick, (i, t) -> i)
.subscribe(System.out::println);
scheduler.advanceTimeBy(2, TimeUnit.SECONDS);
you have some class:
public class SomeClass {
public void someMethod() {
Observable<Long> tick = Observable.interval(1, TimeUnit.SECONDS);
contactsRepository.find(index)
.buffer(MAX_CONTACTS_FETCH)
.zipWith(tick, new Func2<List<ContactDto>, Long, List<ContactDto>>() {
@Override
public List<ContactDto> call(List<ContactDto> contactList, Long aLong) {
return contactList;
}
}).subscribe()
}
}
Look up [Observable.interval][1]
in the docs and you will see it operates on the computation scheduler, so lets override that in our test.
public class SomeClassTest {
private TestScheduler testScheduler;
@Before
public void before() {
testScheduler = new TestScheduler();
// set calls to Schedulers.computation() to use our test scheduler
RxJavaPlugins.setComputationSchedulerHandler(ignore -> testScheduler);
}
@After
public void after() {
// reset it
RxJavaPlugins.setComputationSchedulerHandler(null);
}
@Test
public void test() {
SomeClass someInstance = new SomeClass();
someInstance.someMethod();
// advance time manually
testScheduler.advanceBy(1, TimeUnit.SECONDS);
}
This solution is an improvement to the accepted answer as the quality, integrity and simplicity of the production code is maintained.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With