使用 Jest 在 Redux thunk 中测试分派的操作

新手上路,请多包涵

我对 Jest 很陌生,并且诚然我不是测试异步代码的专家……

我有一个简单的 Fetch 我使用的助手:

 export function fetchHelper(url, opts) {
    return fetch(url, options)
        .then((response) => {
            if (response.ok) {
                return Promise.resolve(response);
            }

            const error = new Error(response.statusText || response.status);
            error.response = response;

            return Promise.reject(error);
        });
    }

并像这样实现它:

 export function getSomeData() {
    return (dispatch) => {
        return fetchHelper('http://datasource.com/').then((res) => {
            dispatch(setLoading(true));
            return res.json();
        }).then((data) => {
            dispatch(setData(data));
            dispatch(setLoading(false));
        }).catch(() => {
            dispatch(setFail());
            dispatch(setLoading(false));
        });
    };
}

但是,我想测试是否在正确的情况下以正确的顺序触发了正确的调度。

使用 sinon.spy() 过去这很容易,但我不太清楚如何在 Jest 中复制它。理想情况下,我希望我的测试看起来像这样:

 expect(spy.args[0][0]).toBe({
  type: SET_LOADING_STATE,
  value: true,
});

expect(spy.args[1][0]).toBe({
  type: SET_DATA,
  value: {...},
});

提前感谢您的任何帮助或建议!

原文由 DanV 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 397
1 个回答

redux 文档有 一篇关于测试异步操作创建者 的很棒的文章:

对于使用 Redux Thunk 或其他中间件的异步操作创建者,最好完全模拟 Redux 存储以进行测试。您可以使用 redux-mock-store 将中间件应用于模拟商店。您还可以使用 fetch-mock 模拟 HTTP 请求。

 import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
import * as actions from '../../actions/TodoActions'
import * as types from '../../constants/ActionTypes'
import fetchMock from 'fetch-mock'
import expect from 'expect' // You can use any testing library

const middlewares = [thunk]
const mockStore = configureMockStore(middlewares)

describe('async actions', () => {
  afterEach(() => {
    fetchMock.reset()
    fetchMock.restore()
  })

  it('creates FETCH_TODOS_SUCCESS when fetching todos has been done', () => {
    fetchMock
      .getOnce('/todos', { body: { todos: ['do something'] }, headers: { 'content-type': 'application/json' } })

    const expectedActions = [
      { type: types.FETCH_TODOS_REQUEST },
      { type: types.FETCH_TODOS_SUCCESS, body: { todos: ['do something'] } }
    ]
    const store = mockStore({ todos: [] })

    return store.dispatch(actions.fetchTodos()).then(() => {
      // return of async actions
      expect(store.getActions()).toEqual(expectedActions)
    })
  })
})

他们的方法不是使用 jest(或 sinon)来监视,而是使用 mock store 并断言已派发的操作。这具有能够处理 thunk 派遣 thunk 的优势,这对于间谍来说很难做到。

这一切都直接来自文档,但如果您想让我为您的 thunk 创建一个示例,请告诉我。

原文由 Michael Peyper 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进