如何为使用useAppDispatch与Redux Toolkit Slice的React自定义Hook编写测试?
解决自定义React Hook(Redux Toolkit + TypeScript)的Jest测试报错
问题分析
你的测试代码存在三个核心问题:
- 错误尝试Spy独立导出的
useAppDispatch函数,Jest无法通过这种方式mock函数模块 - 未mock依赖的工具函数
getStringToTheTemplate,导致测试依赖真实函数的行为 - 不必要地Spy Redux Toolkit自动生成的action creator,违背RTK测试的最佳实践
修正后的测试代码
import { useFields } from "../ForgetPassword/data"; // Mock整个redux模块,包括useAppDispatch jest.mock("../../app/redux", () => ({ useAppDispatch: jest.fn(), })); // Mock工具函数getStringToTheTemplate jest.mock("./utils", () => ({ getStringToTheTemplate: jest.fn((value) => value), // 默认返回原值,可按需修改 })); // 导入被mock后的模块 import { useAppDispatch } from "../../app/redux"; import { registrationFormSlice } from "../../entities/registration"; import { getStringToTheTemplate } from "./utils"; describe("useFields hook", () => { const dispatchMock = jest.fn(); beforeEach(() => { // 给mock的useAppDispatch设置返回值 (useAppDispatch as jest.Mock).mockReturnValue(dispatchMock); // 重置所有mock dispatchMock.mockReset(); (getStringToTheTemplate as jest.Mock).mockReset(); }); it("should call dispatch with transformed value via setLastName action", () => { const getFields = useFields(); const lastNameField = getFields()[0][0]; const testValue = "Test"; const transformedValue = "TransformedTest"; // 手动指定工具函数的返回值,模拟转换行为 (getStringToTheTemplate as jest.Mock).mockReturnValue(transformedValue); lastNameField.setValue(testValue); // 验证工具函数被调用 expect(getStringToTheTemplate).toHaveBeenCalledWith(testValue); // 验证dispatch被调用,且参数是正确的action expect(dispatchMock).toHaveBeenCalledTimes(1); expect(dispatchMock).toHaveBeenCalledWith( registrationFormSlice.actions.setLastName(transformedValue) ); }); it("should return correct fields array structure", () => { const getFields = useFields(); const fields = getFields(); expect(fields).toEqual([ [ { label: "lastName", valueKey: "lastName", setValue: expect.any(Function), }, ], ]); // 额外验证数组长度和字段类型 expect(fields.length).toBe(1); expect(fields[0].length).toBe(1); expect(typeof fields[0][0].setValue).toBe("function"); }); });
关键修改说明
Mock整个模块而非Spy函数
使用jest.mock("../../app/redux")来mock整个包含useAppDispatch的模块,完全控制该函数的返回值,避免Spy独立函数的无效操作。Mock工具函数
getStringToTheTemplate
通过jest.mock("./utils")mock工具函数,测试时可手动指定返回值,确保测试不依赖真实函数的转换逻辑,专注于Hook本身的行为。验证Dispatch的Action而非Spy Action Creator
RTK的action creator是纯函数,直接验证dispatch被调用的action内容(通过registrationFormSlice.actions.setLastName(transformedValue)生成的action对象),这是Redux测试的标准做法,比Spy action creator更可靠。TypeScript类型处理
使用as jest.Mock断言mock后的函数类型,解决TypeScript的类型检查问题。
内容的提问来源于stack exchange,提问作者BuGaGa
相关产品推荐
相关产品推荐

