如何Mock Redux Thunk异步Action返回值用于组件测试(仅函数Mock无真实请求)
正确实现方案
你当前的错误主要来自3个问题:
- 对
createAsyncThunk生成的异步thunk函数的mock格式错误,thunk函数调用后会返回一个接收dispatch作为参数的嵌套函数,你直接返回了action对象,无法被dispatch正常执行 - 多余的
spyOn操作,setTestData不是TestPage的导出项,你不需要对它做spy处理 - 渲染组件的逻辑放在了
waitFor内部,执行顺序错误
正确的mock和测试代码
首先修改mock逻辑,让它返回符合thunk规范的函数,注意匹配原模块的默认导出格式:
// 直接mock整个testService模块 jest.mock('../redux/asyncServices/testService', () => { // 模拟createAsyncThunk生成的thunk函数 const mockSetTestData = () => async (dispatch) => { dispatch({ type: "setTestData/fulfilled", payload: { user: {name: 'Loaded user name'} } }) }; // 匹配原模块的ES默认导出规则 return { __esModule: true, default: mockSetTestData }; });
然后修改测试用例逻辑:
import TestPage from '../pages/TestPage'; import {screen, waitFor} from '@testing-library/react'; describe('Timesheet Menu page tests', () => { beforeEach(() => { matchMedia = new MatchMediaMock() }) afterEach(() => { matchMedia.clear() jest.clearAllMocks() }) test('Component renders correctly', async () => { // 先渲染组件,触发useEffect里的dispatch逻辑 renderWithRedux(<TestPage/>, {initialState}) // 等待异步thunk执行完成,用户名渲染 await waitFor(() => { expect(screen.getByText('Loaded user name')).toBeInTheDocument() }) expect(screen.getByText('Test')).toBeInTheDocument() }) })
补充优化点
如果你的reducer对pending状态也做了处理,mock的时候可以加上pending状态的dispatch,更贴近真实的异步流程:
const mockSetTestData = () => async (dispatch) => { dispatch({type: "setTestData/pending"}) await new Promise(resolve => setTimeout(resolve, 0)) dispatch({ type: "setTestData/fulfilled", payload: {user: {name: 'Loaded user name'}} }) };
内容的提问来源于stack exchange,提问作者DevOverflow
相关产品推荐
相关产品推荐

