2017-05-29 172 views
2

我有一個函數可以查詢api,直到返回所需的結果或者達到超時時間。單元測試Observable.interval

// sample poll, filter and timeout 
    pollStatus =(): Observable<string> => { 
      return Observable.interval(1000) 
       .mergeMap(() => this.getStatus(); // this makes a http call to a status api 
       .map((response) => response.json()) 
       .filter((responseData) => responseData.status !== 'PENDING') 
       .take(1) 
       .map((response) => response.status) 
       .catch((error) => Observable.throw({message: 'FAILED'})) 
       .timeout(5000); 
      }; 

在我的測試我想執行的pollStatus()函數,並確保的getStatus()函數被調用的時間等正確的號碼,但我不能活動得到它調用它一次。測試Observable.interval的最佳方式是什麼,以及如何強制發生新的時間間隔?

+0

如果你在Angular裏面,你需要使用FakeAsync和Angular的實用工具。 –

+0

謝謝Julia。我結束了與fakeAsync方法 – BSimpson

回答

0

要測試Rx代碼,您需要通過VirtualTimeScheduler,這樣您才能在測試中提前計算時間。您可以使用compat的包@kwonoj/rxjs-testscheduler-compat所以你可以寫在RxJs5測試,你會在RxJs4已經寫了他們:

import { TestScheduler, next, complete } from '@kwonoj/rxjs-testscheduler-compat'; 

const scheduler = new TestScheduler(); 
const results = scheduler.startScheduler(
() => pollStatus(scheduler), 
    { created: 100, subscribed: 200, unsubscribed: 4000 } 
); 

您需要調度傳遞到基於時間的運營商,使他們將安排他們的工作不在默認的調度,但您提供的一個:

pollStatus = (scheduler?:Rx.Scheduler): Observable<string> => { 
    return Observable.interval(1000, scheduler) 
    .mergeMap(() => this.getStatus(); // this makes a http call to a status api 
    .map((response) => response.json()) 
    .filter((responseData) => responseData.status !== 'PENDING') 
    .take(1) 
    .map((response) => response.status) 
    .catch((error) => Observable.throw({message: 'FAILED'})) 
    .timeout(5000, scheduler); 
}; 

然後,您可以觀察到你的代碼在虛擬時間運行在您的測試,然後你就可以開始爲this.getStatus()創建嘲笑有它慢則5000毫秒所以你的timeout()命中等

+0

感謝馬克。我會盡力去回報。我假設我無法避免將調度程序傳遞到函數中,因爲它僅用於測試? – BSimpson

+0

你可以嘗試使用諸如https://github.com/tchock/RxJS-TestScheduler-Injector –

+0

之類的東西將調度器注入rx函數。感謝您的建議Mark。我無法使測試與Scheduler配合使用以進行測試。我結束了使用fakeAsync()和tick() – BSimpson