2017-05-29 80 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