为什么jest.useFakeTimers不能使用RxJs Observable延迟

blo*_*ork 3 javascript unit-testing rxjs jestjs asynctest

我想知道为什么jest.useFakeTimerssetTimeoutRxJs的延迟运算符一起工作但不是:

jest.useFakeTimers();
import {Observable} from 'rxjs/Observable';
import 'rxjs';

describe('timers', () => {
    it('should resolve setTimeout synchronously', () => {
        const spy = jest.fn();
        setTimeout(spy, 20);
        expect(spy).not.toHaveBeenCalled();
        jest.runTimersToTime(20);
        expect(spy).toHaveBeenCalledTimes(1);
    });
    it('should resolve setInterval synchronously', () => {
        const spy = jest.fn();
        setInterval(spy, 20);
        expect(spy).not.toHaveBeenCalled();
        jest.runTimersToTime(20);
        expect(spy).toHaveBeenCalledTimes(1);
        jest.runTimersToTime(20);
        expect(spy).toHaveBeenCalledTimes(2);
    });
    it('should work with observables', () => {
        const delay$ = Observable.of(true).delay(20);
        const spy = jest.fn();
        delay$.subscribe(spy);
        expect(spy).not.toHaveBeenCalled();
        jest.runTimersToTime(2000);
        expect(spy).toHaveBeenCalledTimes(1);
    });
});
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

仅供参考:使用20或2000作为参数jest.runTimersToTime没有任何区别.使用jest.runAllTimers()使测试过去

car*_*ant 6

delay,因为运营商不与玩笑的假定时器工作delay是无关的假时间玩笑的概念-运营商实现使用时间的调度的概念.

来源在这里:

while (queue.length > 0 && (queue[0].time - scheduler.now()) <= 0) {
  queue.shift().notification.observe(destination);
}
Run Code Online (Sandbox Code Playgroud)

当前(非假)时间在创建时分配给通知,并且当前时间是调度程序now方法返回的时间.当使用Jest的假定时器时,实际(非假)时间量将不足,通知将保留在队列中.

要使用假或虚拟时间编写RxJS测试,您可以使用VirtualTimeScheduler.看到这个答案.或者你可以使用TestScheduler大理石测试.