在使用 Redux 进行前端开发时,我们经常会使用 thunk 中间件来进行异步操作。然而,在编写 thunk 函数时,我们也需要编写相应的单元测试来保证代码的质量和正确性。本文将介绍 Redux 的 thunk 单元测试的基本知识以及如何编写单元测试,希望能对 Redux 初学者有所帮助。
什么是 Redux 的 thunk 中间件
Redux 的 thunk 中间件是用于处理异步操作的一个中间件。它允许我们在 Redux 应用中编写 action creators,这些 action creators 返回的不再是一个普通的 action 对象,而是一个函数,这个函数可以接受 dispatch 函数和 getState 函数作为它的参数,从而可以完成异步操作或者多个 action 的组合操作。
如何编写 Redux 的 thunk 单元测试
Redux 的 thunk 单元测试需要使用到一些开发工具,比如 Jest 和 Enzyme,下面将介绍如何使用 Jest 和 Enzyme 编写 Redux 的 thunk 单元测试。
测试异步操作的 action creators
我们可以使用 Jest 提供的 mock 和 Promise 对象来测试异步操作的 action creators。例如,我们有一个异步的 action creators:
// javascriptcn.com 代码示例 export const fetchUser = (userId) => (dispatch) => { dispatch(fetchUserRequest()); return axios.get(`/api/users/${userId}`) .then(({ data }) => { dispatch(fetchUserSuccess(data)); }) .catch((error) => { dispatch(fetchUserError(error)); }); };
我们可以使用 Jest 提供的 mock 和 Promise 对象来测试这个 action creators:
// javascriptcn.com 代码示例 import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import axios from 'axios'; import { fetchUser } from './userActions'; import { FETCH_USER_REQUEST, FETCH_USER_SUCCESS, FETCH_USER_ERROR, } from './userActionTypes'; const mockStore = configureMockStore([thunk]); jest.mock('axios'); describe('userActions', () => { it('should dispatch FETCH_USER_SUCCESS when fetchUser is done', () => { const user = { id: 1, name: 'John Doe' }; const store = mockStore({}); axios.get.mockResolvedValue({ data: user }); return store.dispatch(fetchUser(1)) .then(() => { const actions = store.getActions(); expect(actions[0].type).toEqual(FETCH_USER_REQUEST); expect(actions[1].type).toEqual(FETCH_USER_SUCCESS); expect(actions[1].payload).toEqual(user); }); }); });
在上面的代码中,我们使用 Jest 提供的 mock 函数模拟了 axios 的 get 请求,然后通过编写测试函数来测试异步操作的 action creators。在这个单元测试中,我们使用了 redux-mock-store 模块来创建一个假的 store,然后调用异步操作的 action creators,使用 Enzyme 获取 store 中得到的 actions 数组,最后使用 expect 断言判断我们预期的 action 是否正确。
测试组合操作的 action creators
如果我们的 action creators 是由多个 action creators 组合而成的,那么我们需要使用 Redux 的 applyMiddleware 函数来应用 thunk 中间件,从而使得我们可以 dispatch 一个函数,而不仅仅是一个普通的 action 对象。例如,我们有一个组合操作的 action creators:
export const fetchUserAndName = (userId) => async (dispatch) => { await dispatch(fetchUser(userId)); const user = getState().user; await dispatch(fetchUserName(user.nameId)); };
我们需要使用 applyMiddleware 函数来测试这个 action creators:
// javascriptcn.com 代码示例 import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import axios from 'axios'; import { fetchUserAndName } from './userActions'; import { FETCH_USER_REQUEST, FETCH_USER_SUCCESS, FETCH_USER_ERROR, FETCH_USER_NAME_REQUEST, FETCH_USER_NAME_SUCCESS, FETCH_USER_NAME_ERROR, } from './userActionTypes'; const mockStore = configureMockStore([thunk]); jest.mock('axios'); describe('userActions', () => { it('should dispatch FETCH_USER_SUCCESS and FETCH_USER_NAME_SUCCESS when fetchUserAndName is done', () => { const user = { id: 1, name: 'John Doe', nameId: 1 }; const userName = { id: 1, name: 'John' }; const store = mockStore({ user: {} }); axios.get.mockResolvedValueOnce({ data: user }); axios.get.mockResolvedValueOnce({ data: userName }); return store.dispatch(fetchUserAndName(1)) .then(() => { const actions = store.getActions(); expect(actions[0].type).toEqual(FETCH_USER_REQUEST); expect(actions[1].type).toEqual(FETCH_USER_SUCCESS); expect(actions[1].payload).toEqual(user); expect(actions[2].type).toEqual(FETCH_USER_NAME_REQUEST); expect(actions[3].type).toEqual(FETCH_USER_NAME_SUCCESS); expect(actions[3].payload).toEqual(userName); }); }); });
在上面的代码中,我们使用 applyMiddleware 函数来应用 thunk 中间件,然后使用 Enzyme 来测试组合操作的 action creators。在测试函数中,我们首先 mock 掉了 axios 的两个 get 请求,然后调用组合操作的 action creators,最后使用 expect 断言判断我们预期的 action 是否正确。
总结
Redux 的 thunk 中间件提供了一种优雅的方式来处理异步操作,然而,在编写 thunk 函数时,我们也需要编写相应的单元测试来保证代码的质量和正确性。本文介绍了 Redux 的 thunk 单元测试的基本知识以及如何使用 Jest 和 Enzyme 编写单元测试,希望对 Redux 初学者有所帮助。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/654cb1637d4982a6eb61b781