redux-observable Promise在单元测试中没有得到解决 [英] redux-observable Promise is not getting resolved in unit test

查看:122
本文介绍了redux-observable Promise在单元测试中没有得到解决的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试测试此史诗类 https://github .com/zarcode/unsplashapp/blob/master/src/epics/photos.js .问题是在运行测试时map永远不会发生(我认为这意味着Promise永远不会解决),所以photosSuccess动作也永远不会发生:

I am trying to test this epic https://github.com/zarcode/unsplashapp/blob/master/src/epics/photos.js . Problem is that map never happens when I run test (which I assume means that Promise never resolves), so photosSuccess action never happens also:

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,诺言就会得到解决,并且会在控制台日志中得到结果.

However, if I do requestAction.subscribe promise gets resolved and I get the result in the console log.

注意:仅当我运行此测试时才会发生这种情况

Note: this happens only when I run this test https://github.com/zarcode/unsplashapp/blob/master/src/epics/photos.test.js, app code works fine, data is fetching fine.

问题是:如何正确编写此测试?

Question is: How to write this test properly?

推荐答案

测试异步代码时请保持警惕,如

Keep mind when testing async code you need to use different strategies, as noted in the documentation.

在尝试测试异步代码之前,我遇到了很多问题,大多数问题是测试在确定已解决的承诺被处理之前就断言了预期的行为,并且断言需要在下一个滴答声中进行. 事件循环 setImmediate中的断言,也可以用setTimeout来实现.

I crossed with a lot of problems before trying to test my async code, most of the problems were that the test was asserting the expected behavior before the resolved promise could be processed, and the assertion needed to be made in the next tick of the event loop, which I in practice achieve by putting the assertion inside a setImmediate, which can be achieved with a setTimeout too.

从玩笑的文档中,您可以更改测试并通过done回调,像平常一样调度触发操作,但是将断言放入具有1 ms超时的setTimeout回调中,只是允许已解决的承诺要进行处理,则将调用回调,并将断言所需的状态.

From the documentation of jest, you can change your test and pass the done callback, dispatch the triggering action as normal, but put the assertion inside a setTimeout callback with 1 ms timeout, just to allow the resolved promised to be processed, then the callback will be called and it will assert the desired state.

可以使用其他策略,例如async/await,或者可以代替使用setTimeout来解决一个空的Promise并将断言放入then回调中.请记住,如果在测试流程中存在更多的Promises,则在实现所需的输出之前,必须在事件循环上添加更多的滴答声.

Other strategies can be used, like async/await, or you can instead of using setTimeout, resolve an empty Promise and put the assertion into the then callback. Just keep in mind that if more Promises exist within the tested flow, more ticks on the event loop will be necessary until the desired output is achieved to be asserted.

实现:

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

这篇关于redux-observable Promise在单元测试中没有得到解决的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆