【问题标题】:How to use TestScheduler in RxJava如何在 RxJava 中使用 TestScheduler
【发布时间】:2014-11-02 12:11:48
【问题描述】:

我应该如何使用 RxJava 的TestScheduler?我来自 .NET 背景,但 RxJava 中的 TestScheduler 似乎与 .NET rx 中的测试调度程序的工作方式不同。

这是我要测试的示例代码

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()

我试过了:

subscribeOn(testScheduler)
testScheduler.advanceTimeBy(2, TimeUnit.SECONDS);
testScheduler.triggerActions();

没有运气。

【问题讨论】:

  • 您不会将TestScheduler 传递给Observable.Interval。这在 .NET 中也是一个问题。

标签: rx-java


【解决方案1】:

我做了一个小例子来说明如何使用TestScheduler。我认为它与 .NET 实现非常相似

@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

编辑 根据您的代码:您应该将调度程序传递给Observable.interval 操作,因为这是您要控制的:

    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);

【讨论】:

  • 是的,这很棒,但是测试一段“真实/”代码怎么样,让我们​​留下一个带有 Observable 订阅者的方法,该方法执行一些回调 onComplete 和一些其他回调 onError。我已经在subscribeOn 中注入了测试调度程序,但从那里没有运气。
【解决方案2】:

你有一些课程:

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()
  }
}

在文档中查找 [Observable.interval][1],您将看到它在计算调度程序上运行,因此让我们在测试中覆盖它。

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);
  }

此解决方案是对公认答案的改进,因为生产代码的质量、完整性和简单性得以保持。

【讨论】:

  • 谢谢!我正在使用throttleFirst,但我的测试失败了,因为它没有像我的 TestScheduler 那样提前时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多