2014-11-02 70 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