如何模拟 RxJs 6 计时器? [英] How do I mock RxJs 6 timer?

查看:14
本文介绍了如何模拟 RxJs 6 计时器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们最近从 Angular 5 更新到了 Angular 6,以及 RxJs 6.作为迁移的一部分,计时器的使用已从:

We've recently updated from Angular 5 to Angular 6, and with it RxJs 6. As part of the migration, the timer usage has changed from:

Observable.timer()

timer()

在我们的测试中有很多地方我们使用以下模式模拟计时器可观察对象.

There are a number of places in our tests where we mock timer observables with the following pattern.

let timerObserver: Observer<any>;

 beforeEach(() => {
 spyOn(Observable, 'timer').and.returnValue(Observable.create(
    ((observer: Observer<any>) => {
      timerObserver  = observer;
    })
  ));
});

it(`should not have any notifications by default`, () => {
   timerObserver.next('');
   ...
});

有人知道如何迁移这种模式吗?

Does anybody know how to migrate this pattern across?

我在这里创建了问题的简化说明:

I've created a simplified illustration of the problem here:

https://stackblitz.com/edit/angular-v6-testing-模板-nm7add

// Hello.Component
      ngOnInit() {
        const timer$ = timer(30);
        timer$.subscribe(() => {
          this.testMe = 'this has been changed';
        });
      }

// Hello.component.spec
  it('should set testMe after a given timer', fakeAsync(() => {
    tick(50);
    expect(fixture.componentInstance.testMe).toBe('this has been changed');
  }));

在这个例子中,我试图让计时器触发而不等待计时器解决.

In this example, I'm trying to get timer to trigger without waiting for the timer to resolve.

推荐答案

当您使用 fakeAsync 时,您可以依靠它对 setInterval 的修补来伪造 timer observable 的实现.

As you are using fakeAsync, you can rely upon its patching of setInterval to fake the implementation of the timer observable.

但是,您需要破坏 asyncScheduler 实例的 now 方法,因为它返回 Date.now().(严格来说,这对于 timer 可观察对象来说不是必需的,因为您已经使用了它,但它对于其他一些可观察对象很重要 - 例如由 delay 运算符).

However, you will need to clobber the asyncScheduler instance's now method, as it returns Date.now(). (Strictly speaking, this isn't necessary for the timer observable, as you've used it, but it will matter for some other observables - e.g. the observable returned by the delay operator).

如果您使用 beforeEachafterEach 来破坏 now 方法并配置一个保持追踪虚假时间:

You can get things to work pretty easily if you use beforeEach and afterEach to clobber the now method and to configure a function that keeps track of the fake time:

import { fakeAsync, tick as _tick } from '@angular/core/testing';
import { asyncScheduler, of, timer } from 'rxjs';
import { delay } from 'rxjs/operators';

describe('fakeAsync and RxJS', () => {

  let tick: (milliseconds: number) => void;

  beforeEach(() => {
    let fakeNow = 0;
    tick = milliseconds => {
      fakeNow += milliseconds;
      _tick(milliseconds);
    };
    asyncScheduler.now = () => fakeNow;
  });

  it('should support timer with fakeAsync', fakeAsync(() => {
    const source = timer(100);
    let received: number | undefined;
    source.subscribe(value => received = value);
    tick(50);
    expect(received).not.toBeDefined();
    tick(50);
    expect(received).toBe(0);
  }));

  it('should support delay with fakeAsync', fakeAsync(() => {
    const source = of(0).pipe(delay(100));
    let received: number | undefined;
    source.subscribe(value => received = value);
    tick(50);
    expect(received).not.toBeDefined();
    tick(50);
    expect(received).toBe(0);
  }));

  afterEach(() => {
    delete asyncScheduler.now;
  });
});

<小时>

实际上,因为依靠 fakeAsync 来模拟基于时间的 observable 可能很有用,所以我在 rxjs-marbles 包.请参阅 fake-spec.ts 例如用法.


Actually, because relying upon fakeAsync to mock the time-based observable is likely to be useful, I've added a fakeSchedulers function to my rxjs-marbles package. See fake-spec.ts for example usage.

实现与上面的代码片段基本相同 - 只是封装在一个函数中.

The implementation is basically the same as that in the above snippet - just wrapped up in a function.

自从写了这个答案并将 fakeSchedulers 添加到 rxjs-marbles 之后,我写了一篇关于 使用假时间进行测试.

Since writing this answer and adding fakeSchedulers to rxjs-marbles, I've written an article about Testing with Fake Time.

这篇关于如何模拟 RxJs 6 计时器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆