Dashboard模块测试用例报错:Actions需为纯对象,实际类型为function
问题解决:测试用例中Redux异步Action报错
报错根源
你的组件里调用的getTotalEmployees和getTotalRes是Redux Thunk异步Action(返回函数的类型),但测试代码里创建Redux Store时,没有配置redux-thunk中间件——原生Redux Store只能处理普通对象类型的Action,无法识别函数类型的Action,这就是报错的核心原因。
另外测试里还有两个小问题:
- 你断言的Action Type和实际代码里的不匹配(实际是
FETCH_TOTAL/FETCH_TOTAL_RES,测试里写的是GET_TOTAL_EMPLOYEES/GET_TOTAL_RES) - 直接监听
React.useEffect的测试方式不够可靠,容易受其他代码干扰
修复步骤
1. 给测试Store添加redux-thunk中间件
项目里肯定已经安装了redux-thunk(前端运行正常),直接在测试代码里导入并配置:
import React from 'react'; import { render, fireEvent, waitForElement } from '@testing-library/react'; import Dashboard from '../Pages/dashboard/Dashboard'; import { Provider } from 'react-redux'; import { createStore, applyMiddleware } from 'redux'; // 新增applyMiddleware import thunk from 'redux-thunk'; // 导入thunk中间件 import { Router } from 'react-router-dom'; import { createMemoryHistory } from 'history'; const setup = () => { // 创建带thunk中间件的Store const initialState = { employees: { employees: [ { _id: '1', username: 'Employee 1', createdAt: new Date().toJSON() }, { _id: '2', username: 'Employee 2', createdAt: '2022-12-12T00:00:00.000Z' }, ], }, results: { results: [{ empId: '1', result: 'pass' }], }, }; const store = createStore( (state = initialState) => state, applyMiddleware(thunk) // 加入thunk,让Store能处理函数型Action ); const history = createMemoryHistory(); const utils = render( <Provider store={store}> <Router location={history.location} navigator={history}> <Dashboard /> </Router> </Provider> ); return { ...utils, store }; };
2. 修正Action Type的断言
把测试里的期望Type改成和实际代码一致的:
test('getTotalEmployees and getTotalRes actions are dispatched', () => { const { store } = setup(); // 匹配Action里实际dispatch的Type expect(store.getActions()).toEqual([ { type: 'FETCH_TOTAL', payload: '' }, { type: 'FETCH_TOTAL_RES' }, ]); });
3. 优化useEffect的测试方式(可选但更合理)
直接监听React.useEffect不是最佳实践,建议通过跟踪dispatch调用验证逻辑:
test('useEffect dispatches actions on mount and currentId change', () => { const mockDispatch = jest.fn(); // mock useDispatch方法 jest.spyOn(require('react-redux'), 'useDispatch').mockReturnValue(mockDispatch); render( <Router location={createMemoryHistory().location} navigator={createMemoryHistory()}> <Dashboard /> </Router> ); // 验证初始挂载时调用了两次dispatch expect(mockDispatch).toHaveBeenCalledTimes(2); // 验证调用的是正确的异步Action函数 expect(mockDispatch).toHaveBeenCalledWith(expect.any(Function)); expect(mockDispatch).toHaveBeenCalledWith(expect.any(Function)); // 清理mock require('react-redux').useDispatch.mockRestore(); });
额外优化:Mock异步请求
如果不想测试时触发真实网络请求,可以mock掉API调用:
// 在测试文件顶部mock API模块 jest.mock('../path-to-your-api-module', () => ({ fetchTotalEmployees: jest.fn().mockResolvedValue({ data: [] }), fetchTotalRes: jest.fn().mockResolvedValue({ data: [] }), }));
这样测试就能正常运行,不会再出现Action类型错误了。
内容的提问来源于stack exchange,提问作者lekshmi priya
相关产品推荐
相关产品推荐

