2014-11-02 71 views
10

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

这里是我想测试

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

没有运气。

+0

您不会将'TestScheduler'传递给'Observable.Interval'。这也是.NET的一个问题。 – 2016-09-07 15:07:17

回答

20

我举了一个小例子来说明如何使用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); 
+1

是的,这很好,但是如何测试一个真实的/一段代码,让我们留下你有一个Observable订阅者的方法,该订阅者执行一些回调onComplete和一些其他回调onError。我在'subscribeOn'中注入了测试调度器,但从那里没有运气。 – Calin 2014-11-02 14:05:44

+1

你可以发布一些代码来详细说明你的问题吗? – dwursteisen 2014-11-02 14:19:15

+0

添加样品代码 – Calin 2015-02-18 10:05:03

7

你有一些类:

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

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

+1

谢谢!我正在使用'throttleFirst',我的测试失败了,因为它没有像我的TestScheduler那样提前。 – 2017-08-28 10:09:37