Обещание в редуксе не разрешается в модульном тесте - PullRequest
0 голосов
/ 21 мая 2018

Я пытаюсь проверить эту эпопею https://github.com/zarcode/unsplashapp/blob/master/src/epics/photos.js.Проблема в том, что map никогда не происходит, когда я запускаю тест (что, как я предполагаю, означает, что Promise никогда не разрешается), поэтому действие photosSuccess также никогда не происходит:

export const loadPhotosToList = (action$: Observable<Action>, state$: 
Object): Observable<Action> => {
  const state = (photosFilter: PhotosFilter) => state$.value.photos[photosFilter];
  return action$
  // .ofType(ACTION.FETCH_PHOTOS_REQUESTED)
    .pipe(
      filter((a: Action) =>
        a.type === ACTION.FETCH_PHOTOS_REQUESTED &&
        ((state(a.filter).loadingState === 'idle' && !state(a.filter).isLastPage) || a.refresh)),
      switchMap((a) => {
        const nextPage = !a.refresh ? state(a.filter).lastLoadedPage + 1 : 1;
        const loadingAction = of(photosActions.photosLoading(a.filter, a.refresh));
        const request = api.fetchPhotos({
          page: nextPage,
          per_page: perPage,
          order_by: a.filter,
        });
        const requestAction = from(request)
          .pipe(
            // tap(data => { console.log("data", data); }),
            map(data =>
              photosActions.photosSuccess(
                data,
                a.filter,
                nextPage,
                data.length < perPage,
                a.refresh,
              )),
            catchError(e => of(photosActions.photosFail(e.message, a.filter))),
          );
        // requestAction.subscribe(x => console.log("-------",x));
        return loadingAction
          .pipe(
            concat(requestAction),
            takeUntil(action$
              .pipe(filter(futureAction => futureAction.type === ACTION.FETCH_PHOTOS_REQUESTED))),
          );
      }),
    );
};

Однако, если я выполняю requestAction.subscribe обещаниея получаю результат в журнале консоли.

Примечание: это происходит только при запуске этого теста https://github.com/zarcode/unsplashapp/blob/master/src/epics/photos.test.js, код приложения работает нормально, данные извлекаются нормально.

Вопрос: как правильно написать этот тест?

1 Ответ

0 голосов
/ 26 мая 2018

Помните, что при тестировании асинхронного кода необходимо использовать разные стратегии, как указано в документации .

Я столкнулся с множеством проблем, прежде чем пытаться протестировать мой асинхронный код, большинство проблем заключалось в том, что тест утверждал ожидаемое поведение до того, как разрешенное обещание могло быть обработано, и утверждение нужно было сделать вследующий тик цикла событий , которого я на практике достигаю, помещая утверждение в setImmediate, что также может быть достигнуто с помощью setTimeout.

Из документации jest вы можете изменить свой тест и передать обратный вызов done, отправить запускающее действие как обычно, но поместить утверждение в обратный вызов setTimeout с тайм-аутом в 1 мс, чтобы просторешенное обещание будет обработано, затем будет вызван обратный вызов, и он подтвердит желаемое состояние.

Можно использовать другие стратегии, например async/await, или вместо setTimeout можно разрешить пустое обещание и поместить утверждение в обратный вызов then.Просто имейте в виду, что если в тестируемом потоке существует больше Обещаний, потребуется больше тиков в цикле событий до тех пор, пока не будет достигнут желаемый результат.

РЕДАКТИРОВАТЬ: Реализация:

// test
it('produces the photo model', (done) => {
...
// dispatch epic triggering action
store.dispatch(...);
// assertion
setImmediate(() => {
  expect(store.getActions()).toEqual([
  ...
  ]);
  done();
});
...