我一直坚持这一天。受到Dan Lew great post的启发,我尝试为repeatWhen()和retryWhen()创建一个简单的测试用例:
public class ObsTest {
private static final Logger LOG = LoggerFactory.getLogger(ObsTest.class);
@Test
public void test1() throws InterruptedException {
Observable<Integer> obs = rx.Observable.<Integer> create(observer -> {
LOG.info("onSubscribe");
Integer data = RandomUtils.nextInt(0, 1000);
if (data % 2 != 0) {
observer.onError(new RuntimeException("Odd number " + data));
} else {
observer.onNext(data);
}
observer.onCompleted();
}, BackpressureMode.BUFFER);
obs.repeatWhen(completed -> completed.delay(1, TimeUnit.MILLISECONDS))
.retryWhen(error -> error.delay(1, TimeUnit.MILLISECONDS))
.subscribe(i -> LOG.info("value={}", i), e -> LOG.info("Exception = {}", e.getMessage()));
}
我的想法是这应该永远运行,将偶数作为“正确”结果发出,将奇数作为“错误”发出。 相反,它运行一个或两个循环然后停止。也就是说,当延迟为1毫秒时,在较长的时间段内(即1秒),它会运行一次,只发出一个奇数或偶数。 我确定我做错了什么,但我找不到它是什么。
答案 0 :(得分:2)
默认情况下,当您调用使用delay
的{{1}}时,您会引入异步。一旦活动开始在后台线程中发生,您的测试就会完成,并且可能会退出您的过程。您需要使用Schedulers.computation()
或在结尾放置一个较长的blockingSubscribe
。
答案 1 :(得分:0)
正如Dave Moten所述,delay
默认使用Schedulers.computation()
,但是您可以改为通过您选择的scheduler
-为了进行测试,您可以使用TestScheduler
和“控制时间”。下面的代码显示了如何使用它-如您所见,该订阅将在30天后不再终止,这基本上是永远的;)
public class ObsTest {
@Test
public void test1() {
Observable<Integer> obs = rx.Observable.create(observer -> {
Integer data = RandomUtils.nextInt(0, 1000);
if (data % 2 != 0) {
observer.onError(new RuntimeException("Odd number " + data));
} else {
observer.onNext(data);
}
observer.onCompleted();
}, Emitter.BackpressureMode.BUFFER);
TestScheduler scheduler = Schedulers.<Integer>test();
AssertableSubscriber subscriber = obs.repeatWhen(completed -> completed.delay(1, TimeUnit.MILLISECONDS, scheduler))
.retryWhen(error -> error.delay(1, TimeUnit.MILLISECONDS, scheduler))
.subscribeOn(scheduler)
.test();
subscriber.assertNoValues();
scheduler.advanceTimeBy(30, TimeUnit.SECONDS);
subscriber.assertNoTerminalEvent();
scheduler.advanceTimeBy(30, TimeUnit.DAYS);
subscriber.assertNoTerminalEvent();
}
}