Как мне издеваться над таймером RxJs 6? - PullRequest
0 голосов
/ 08 июня 2018

Мы недавно обновили с Angular 5 до Angular 6 и вместе с ним RxJs 6. В рамках миграции использование таймера изменилось с:

Observable.timer()

на

timer()

В наших тестах есть ряд мест, где мы смоделируем наблюдаемые по таймеру со следующим шаблоном:

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('');
   ...
});

Кто-нибудь знает, как перенести этот шаблон через?


Редактировать: Я создал упрощенную иллюстрацию проблемы здесь:

https://stackblitz.com/edit/angular-v6-testing-template-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');
  }));

В этом примере я пытаюсь заставить таймертриггер, не дожидаясь разрешения таймера.

1 Ответ

0 голосов
/ 09 июня 2018

Поскольку вы используете fakeAsync, вы можете положиться на его исправление setInterval, чтобы подделать реализацию наблюдаемой timer.

Однако вам нужно будет заткнуть экземпляр asyncSchedulernow метод, поскольку он возвращает Date.now().(Строго говоря, это не обязательно для timer наблюдаемой, как вы ее использовали, но это будет иметь значение для некоторых других наблюдаемых - например, наблюдаемая, возвращаемая оператором delay).

Вы можете заставить вещи работать довольно легко, если вы используете beforeEach и afterEach для подавления метода now и для настройки функции, которая отслеживает фальшивое время:

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 для имитации наблюдаемой на основе времени вероятности будет полезно, я добавил функцию fakeSchedulers в свой пакет rxjs-marbles.См., Например, fake-spec.ts.

Реализация в основном такая же, как в приведенном выше фрагменте - только что обернута в функцию.


Так какнаписав этот ответ и добавив fakeSchedulers к rxjs-marbles, я написал статью о тестировании с поддельным временем .

...