6

我想知道为什么jest.useFakeTimers使用setTimeout但不使用 RxJs 的延迟运算符:

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

在此处输入图像描述

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

4

1 回答 1

12

delay操作员不能使用 Jest 的假计时器,因为操作delay员的实现使用其调度程序的时间概念——这与 Jest 的假时间概念无关。

来源在这里

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

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

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

于 2018-01-15T13:39:25.313 回答