React + Redux-Observable Timeout Marble Тестирование

Я создаю веб-приложение с использованием React и Redux Observables, и я хотел бы создать модульный тест для сценария тайм-аута одного из моих эпиков.

Вот эпос:

export const loginUserEpic = (action$: ActionsObservable<any>, store, { ajax, scheduler }): Observable<Action> =>
  action$.pipe(
    ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION),
    switchMap((action: LoginAction) =>
      ajax({
        url,
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: { email: action.payload.username, password: action.payload.password },
      }).pipe(
        timeout(timeoutValue, scheduler),
        map((response: AjaxResponse) => loginSuccess(response.response.token)),
        catchError((error: Error) => of(loginFailed(error))),
      ),
    ),
  );

А вот и мой тест:

  it('should handle a timeout error', () => {
    // My current timeout value is 20 millseconds
    const inputMarble = '------a';
    const inputValues = {
      a: login('fake-user', 'fake-password'),
    };

    const outputMarble = '--b';
    const outputValues = {
      b: loginFailed(new Error('timeout')),
    };

    const ajaxMock = jest.fn().mockReturnValue(of({ response: { token: 'fake-token' } }));
    const action$ = new ActionsObservable<Action>(ts.createHotObservable(inputMarble, inputValues));
    const outputAction = loginUserEpic(action$, undefined, { ajax: ajaxMock, scheduler: ts });

    // I am not sure what error to expect here...
    ts.expectObservable(outputAction).toBe(outputMarble, outputValues);
    ts.flush();
    expect(ajaxMock).toHaveBeenCalled();
  });

Я ожидал, что Epic выдаст ошибку тайм-аута, потому что мое значение тайм-аута составляет 20 мс, а Observer задерживает 60 мс перед выдачей значения. Затем я бы взял эту ошибку и сравнил ее в конце, чтобы пройти тест.

К сожалению, ошибка тайм-аута не возникает. Я делаю что-то неправильно?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
3
0
698
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы используете timeout в цепочке после вызова ajax(), который возвращает только of({ ... }) (ajaxMock), поэтому timeout никогда не запускается, потому что of излучает немедленно.

Если вы хотите протестировать оператор timeout, вам нужно добавить delay в ajaxMock:

const ajaxMock = () => of({ response: { token: 'fake-token' } }).pipe(delay(30, ts));

Вот ваша демонстрация: https://stackblitz.com/edit/rxjs6-demo-pha4qp?file=index.ts

Если запрос на вход начинается с 60 и вы добавляете задержку 30, то на 80 вы получите TimeoutError.

[0: Object
  frame: 80
  notification: Notification
  error: undefined
  hasValue: true
  kind: "N"
  value: Object
    error: Error
      message: "Timeout has occurred"
      name: "TimeoutError"
]

Другие вопросы по теме