Redux-observable:史诗般的笑话测试失败 [英] Redux-observable: failed jest test for epic

查看:146
本文介绍了Redux-observable:史诗般的笑话测试失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遵循了文档中的步骤来测试史诗. /p>

I followed the steps from documentation to test epic.

...
store.dispatch({ type: FETCH_USER });

expect(store.getActions()).toEqual([
   { type: FETCH_USER },
   { type: FETCH_USER_FULFILLED, payload }
]);
...

但是我失败了,因为稍后像下面这样收到了第二个动作.

But I get failed because second action is been received some later like following.

Test failed
    Expected value to equal:
      [{"type": "FETCH_USER"}, {"type": "FETCH_USER_FULFILLED", "payload": [some]}]
    Received:
      [{"type": "FETCH_USER"}]

    Difference:

    - Expected
    + Received

    @@ -1,20 +1,5 @@
     Array [
       Object {"type": "FETCH_USER"},
       Object {"type": "FETCH_USER_FULFILLED", "payload": [some]} ] // this is what should be.

所以我想我应该知道调度何时完成或类似的事情. 我该如何解决?

So I think I should know when the dispatch is finished or some like that. How can I solve this?

我使用了fetch()和Rx.Observable.fromPromise而不是ajax.getJSON()

I used fetch() and Rx.Observable.fromPromise instead of ajax.getJSON()

这是我的史诗.

const fetchUserEpic = (action$) =>
  action$
    .ofType(FETCH_USER)
    .mergeMap(() => {
      return Rx.Observable.fromPromise(api.fetchUser())
        .map((users) => ({
          type: FETCH_USER_FULFILLED,
          payload: { users }
        }))
        .catch((error) => Rx.Observable.of({
          type: FETCH_USER_ERROR,
          payload: { error }
        }))
        .takeUntil(action$.ofType(FETCH_USER_CANCELLED))
    })

推荐答案

原因是承诺总是在

The reason is that promises always resolve on the next microtask so your api.fetchUser() isn't emitting synchronously.

您将需要模拟它,使用Promise.resolve().then(() => expect(store.getActions).toEqual(...)之类的东西等到下一个微任务,或者您可以尝试使用 直接测试您的史诗,而无需使用redux.

You'll need to either mock it out, use something like Promise.resolve().then(() => expect(store.getActions).toEqual(...) to wait until the next microtask, or you can experiment with testing your epics directly without using redux.

it('Epics with the appropriate input and output of actions', (done) => {
  const action$ = ActionsObservable.of({ type: 'SOMETHING' });

  somethingEpic(action$, store)
    .toArray() // collects everything in an array until our epic completes
    .subscribe(actions => {
      expect(actions).to.deep.equal([
        { type: 'SOMETHING_FULFILLED' }// whatever actions
      ]);

      done();
    });
});

当我(或其他人)有时间编写它们时,这将是我们在文档中首选的测试故事.因此,我们无需在测试中使用redux和中间件,而是直接使用我们自己的模拟程序调用epic函数.更轻松,更清洁.

This will be our preferred testing story in the docs when I (or someone else) has time to write them up. So instead of using redux and the middleware in your tests, we just call the epic function directly with our own mocks. Much easier and cleaner.

通过这种方法,我们可以利用redux-observable的新依赖注入功能: https://redux-observable.js.org/docs/recipes/InjectingDependenciesIntoEpics.html

With that approach, we can leverage the new dependency injection feature of redux-observable: https://redux-observable.js.org/docs/recipes/InjectingDependenciesIntoEpics.html

import { createEpicMiddleware, combineEpics } from 'redux-observable';
import { ajax } from 'rxjs/observable/dom/ajax';
import rootEpic from './somewhere';

const epicMiddleware = createEpicMiddleware(rootEpic, {
  dependencies: { getJSON: ajax.getJSON }
});


// Notice the third argument is our injected dependencies!
const fetchUserEpic = (action$, store, { getJSON }) =>
  action$.ofType('FETCH_USER')
    .mergeMap(() =>
      getJSON(`/api/users/${payload}`)
        .map(response => ({
          type: 'FETCH_USER_FULFILLED',
          payload: response
        }))
    );


import { ActionsObservable } from 'redux-observable';
import { fetchUserEpic } from './somewhere/fetchUserEpic';

const mockResponse = { name: 'Bilbo Baggins' };
const action$ = ActionsObservable.of({ type: 'FETCH_USERS_REQUESTED' });
const store = null; // not needed for this epic
const dependencies = {
  getJSON: url => Observable.of(mockResponse)
};

// Adapt this example to your test framework and specific use cases
fetchUserEpic(action$, store, dependencies)
  .toArray() // buffers all emitted actions until your Epic naturally completes()
  .subscribe(actions => {
    assertDeepEqual(actions, [{
      type: 'FETCH_USER_FULFILLED',
      payload: mockResponse
    }]);
  });

这篇关于Redux-observable:史诗般的笑话测试失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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