Тестирование обработки ошибок для эпиков, наблюдаемых с помощью редукции

Здесь я использую redux-observable и у меня проблемы с проверкой обработки ошибок.

См. Следующий эпизод выхода пользователя из системы:

const logoutUserEpic = (action$) => action$
    .ofType(LOGOUT_USER)
    .mergeMap(() =>
        Observable.from(
            graphQl(AuthLogout)
                .catch((error) => failure(error))
        )
        .mergeMap(() => Observable.of(
                receive(),
                push('/login')
            )
        )
    )

Вот тест, который имитирует службу graphQl, чтобы убедиться, что она запускает действие отказа, когда обещание отклоняется:

it('should return the error action', () => {
    const error = Error('fail')
    request.graphQl = () => Promise.reject(error)

    const action$ = ActionsObservable.of((logoutUser()))

    return logoutUserEpic(action$)
    .toArray()
    .forEach((actions) => {
        expect(actions).toEqual([{
            meta: { isFetching: false },
            payload: error,
            type: FAILURE
        }])
    })
})

В тесте он отправляет действия, которые сглаживаются в mergeMap, а не ожидаемое действие сбоя в catch.

Допустимо ли иметь подобную настройку обработки ошибок, или я демонстрирую свое нубизм с RxJs?


person hally9k    schedule 29.04.2017    source источник


Ответы (1)


Проблема в том, что вы обнаруживаете ошибку в самом обещании, а затем ваш mergeMap игнорирует результат обещания, поэтому вы выбрасываете failure(error) (предположительно, действие при ошибке)

const logoutUserEpic = (action$) => action$
    .ofType(LOGOUT_USER)
    .mergeMap(() =>
        Observable.from(
            graphQl(AuthLogout)
                .catch((error) => failure(error))
                // If there is an error, you caught it and transformed it
                // instead into a failure(error) down the success path
        )
        // If there was an error, it is now no longer an error and this
        // mergeMap will just throw that failure(error) away
        .mergeMap(() => Observable.of(
                receive(),
                push('/login')
            )
        )
    )

Вместо этого вы должны отловить ошибку с помощью RxJS, в этом случае поместив ее после _4 _--, обратите внимание, что catch и Promise catch RxJS похожи, но не одно и то же!

const logoutUserEpic = (action$) => action$
  .ofType(LOGOUT_USER)
  .mergeMap(() =>
    Observable.from(graphQl(AuthLogout))
      .mergeMap(() => Observable.of(
        receive(),
        push('/login')
      ))
      .catch((error) => Observable.of(failure(error)))
  )
person jayphelps    schedule 01.05.2017