Как проверить timeout () в трубе rxjs с жасминовыми шариками - PullRequest
1 голос
/ 24 апреля 2019

Я написал канал, который фильтрует входные данные, наблюдаемые.В канале я указываю время ожидания с оператором timeout (), чтобы прервать ожидание, если ожидаемое значение не было получено источником во времени.Я хочу проверить случай тайм-аута с жасминовыми шариками, но не могу заставить его работать.Я полагаю , что expect(source).toBeObservable() оценивает до того, как источник излучает.

см. Stackblitz

Труба, подлежащая проверке:

source = cold('a', { a: { id: 'a' } }).pipe(
  timeout(500),
  filter((a) => false),
  catchError((err) => {
    return of({ timeout: true })
  }),
  take(1)
);

Тестирование с помощью toPromise () работает должным образом:

expect(await source.toPromise()).toEqual({ timeout: true });

Тестирование с использованием жасминового мрамора

const expected = cold('500ms (a|)', { a: { timeout: true } });
expect(source).toBeObservable(expected);

завершается с ошибкой

Expected $.length = 0 to equal 2.
Expected $[0] = undefined to equal Object({ frame: 500, notification: Notification({ kind: 'N', value: Object({ timeout: true }), error: undefined, hasValue: true }) }).
Expected $[1] = undefined to equal Object({ frame: 500, notification: Notification({ kind: 'C', value: undefined, error: undefined, hasValue: false }) }).

1 Ответ

1 голос
/ 24 апреля 2019

Поддержка прогрессии времени была недавно добавлена ​​( см. Jasmine-marbles PR # 38 ) в jasmine-marbles 0.5.0. В пакет были добавлены дополнительные тестовые спецификации, которые демонстрируют один из нескольких возможных способов достичь желаемого. Вот несколько вариантов, которые я смог собрать вместе, используя ваш образец Stackblitz.

Вариант 1

Когда вы инициализируете источник, наблюдаемый за пределами метода теста (например, в beforeEach), вы должны явно инициализировать и передать планировщик теста в timeout, чтобы заставить expect().toBeObservable() работать. Однако обратите внимание, что это изменение нарушит тест «следует работать с toPromise». (Я не знаю почему, но toPromise(), похоже, не работает с этим подходом.)

describe('Marble testing with timeout', () => {

  let source;

  beforeEach(() => {
    // You must explicitly init the test scheduler in `beforeEach`.
    initTestScheduler()
    source = cold('a', { a: { id: 'a' } }).pipe(
      // You must explicitly pass the test scheduler.
      timeout(500, getTestScheduler()),
      filter((a) => false),
      catchError(err => {
        return of({ timeout: true })
      }),
      take(1)
    );
  });

  it('should work with toBeObservable', () => {
    const expected = cold('500ms (a|)', { a: { timeout: true } });
    expect(source).toBeObservable(expected);
  });
});

Вариант 2

Вы можете немного реорганизовать вещи и инициализировать источник, наблюдаемый внутри метода тестирования (, а не в beforeEach). Вам не нужно явно инициализировать планировщик теста (jasmine-marbles сделает это за вас до запуска метода теста), но вам все равно придется передать его в timeout. Обратите внимание, как функция createSource может использоваться с планировщиком тестов или планировщиком по умолчанию (если аргумент scheduler оставлен undefined). Этот параметр работает как с тестом «следует работать с toPromise», так и с тестом «должен работать с toBeObservable».

describe('Marble testing with timeout', () => {

  const createSource = (scheduler = undefined) => {
    return cold('a', { a: { id: 'a' } }).pipe(
      // You must explicitly pass the test scheduler (or undefined to use the default scheduler).
      timeout(500, scheduler),
      filter((a) => false),
      catchError(err => {
        return of({ timeout: true })
      }),
      take(1)
    );
  };

  it('should work with toPromise', async () => {
    const source = createSource();
    expect(await source.toPromise()).toEqual({ timeout: true });
  });

  it('should work with toBeObservable', () => {
    const source = createSource(getTestScheduler());
    const expected = cold('500ms (a|)', { a: { timeout: true } });
    expect(source).toBeObservable(expected);
  });
});

Вариант 3

Наконец, вы можете пропустить передачу планировщика тестов в timeout, если вы явно используете метод run планировщика тестов, но вы должны использовать expectObservable (в отличие от expect().toBeObservable(). Он работает просто отлично, но Jasmine выдаст предупреждение «У СПЕКА НЕТ ОЖИДАНИЙ».

describe('Marble testing with timeout', () => {

  let source;

  beforeEach(() => {
    source = cold('a', { a: { id: 'a' } }).pipe(
      timeout(500),
      filter((a) => false),
      catchError(err => {
        return of({ timeout: true })
      }),
      take(1)
    );
  });

  it('should work with scheduler and expectObservable', () => {
    const scheduler = getTestScheduler();
    scheduler.run(({ expectObservable }) => {
      expectObservable(source).toBe('500ms (0|)', [{ timeout: true }]);
    });
  });
});
...