Как проверить повторную подписку на Rx JS, наблюдаемую в TestScheduler? - PullRequest
0 голосов
/ 23 января 2020

У меня есть наблюдаемое, которое может выдать ошибку. Когда это бросает, я хочу повторно подписаться на это наблюдаемое и попробовать еще раз. Например, с оператором retry().

Чтобы проверить этот retry-logi c Мне нужно создать наблюдаемую проверку, которая будет выдавать ошибку в первые 2 раза, на которые она подписана, и только в 3-й время выдаст значение.

Я попробовал следующее:

import { Observable } from 'rxjs';
import { TestScheduler } from 'rxjs/testing';
import { retry } from 'rxjs/operators';

// Setup for TestScheduler
function basicTestScheduler() {
  return new TestScheduler((actual, expected) => {
    expect(actual).toEqual(expected);
  });
}

// The function we're going to test
function retryMultipleTimes(observable$) {
  return observable$.pipe(retry(2));
}

describe('retryMultipleTimes()', () => {
  it('retries twice when observable throws an error', () => {
    basicTestScheduler().run(({ hot, cold, expectObservable }) => {
      const observable$ = hot('--#--#--Y');
      const expected = '       --------Y'; // This is what I want to get
      const unexpected = '     --#      '; // This is what I get instead

      expectObservable(retryMultipleTimes(observable$)).toBe(expected);
    });
  });
});

Кажется, что при наблюдаемой hot() он всегда повторно подписывается на тот же кадр, который вызвал ошибку, что приводит к немедленному выбрасыванию снова.

Я также пытался с cold() наблюдаемым, в этом случае я получаю ------# - то есть, при каждой повторной попытке наблюдаемое начинается снова с самого начала, что приводит к --#, --#, --# - никогда не достигать --Y.

Похоже, что с Rx JS TestScheduler такого способа не сделать. Или, может быть, есть?

Если hot() и cold() наблюдатели-создатели не справляются с задачей, возможно, я могу создать свою собственную ... но как?

I также попытался добавить небольшую задержку между повторными попытками, поэтому я не стал бы сразу же повторно подписываться на текущий кадр, реализовав retry-logi c, используя retryWhen:

function retryMultipleTimes(observable$) {
  return observable$.pipe(
    retryWhen(errors => errors.pipe(
      delayWhen(() => timer(2)),   // wait 2 frames before each retry
      take(2),                     // do maximum of 2 retries
      concat(throwError('error')), // finish with error when no success after 2 retries
    )),
  );
}

Но это тоже не сработало , Похоже, повторная подписка по-прежнему происходит в том же кадре, что и раньше.

Как я могу пройти этот тест?

1 Ответ

0 голосов
/ 27 января 2020

Разобрался с решением для этого. Я могу использовать iif() для создания наблюдаемой, которая выбирает во время подписки между двумя наблюдаемыми:

describe('retryMultipleTimes()', () => {
  it('retries twice when observable throws an error', () => {
    basicTestScheduler().run(({ cold, expectObservable }) => {
      let count = 0;
      const observable$ = iif(
        () => ++count <= 2,
        cold('--#'),
        cold('--Y'),
      );

      //                                                      --#
      //                                                        --#
      //                                                          --Y
      expectObservable(retryMultipleTimes(observable$)).toBe('------Y');
    });
  });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...