Jest中mock的useHistory.push函数未被调用问题求助
问题:Jest中mock useHistory.push未被触发
我不是Jest mocking专家,尝试mock useHistory的push方法,但点击按钮后mock函数没被触发,求解决办法。
组件代码
const ReviseAction = ({ plans, template, coveragePercentage, territoryName, existingTemplateId, }) => { const history = useHistory(); const handleRevise = () => { history.push({ pathname: "/xxx", state: { plans: plans, template: template, coveragePercentage: coveragePercentage, territoryName: territoryName, existingTemplateId: existingTemplateId, }, }); }; return ( <button data-testid="revise-button" onClick={handleRevise} key="revise-button" > Revise </button> ); };
测试代码
import React from "react"; import { render, screen, fireEvent } from "@testing-library/react"; import ReviseAction from "./ReviseAction"; import { HashRouter as Router } from "react-router-dom"; describe("ReviseAction", () => { jest.mock("react-router-dom"); const pushMock = jest.fn(); //reactRouterDom.useHistory = jest.fn().mockReturnValue({push: pushMock}); jest.mock("react-router-dom", () => ({ ...jest.requireActual("react-router-dom"), useHistory: () => ({ push: jest.fn() }) })); it("Renders component", async () => { render( <Router> <ReviseAction plans={[]} template={{}} coveragePercentage="12" territoryName="Name" existingTemplateId="1234" /> </Router> ); fireEvent.click(screen.queryByTestId("revise-button")); expect(pushMock).toHaveBeenCalled(); }); });
报错信息
Expected number of calls: >= 1
Received number of calls: 0
解决办法
问题根源
你定义的pushMock和mockuseHistory返回的push不是同一个函数:测试里写了两次jest.mock调用,第二个mock覆盖了第一个,且内部用了全新的jest.fn(),和你提前定义的pushMock完全无关。
修正后的测试代码
import React from "react"; import { render, screen, fireEvent } from "@testing-library/react"; import ReviseAction from "./ReviseAction"; import { HashRouter as Router, useHistory } from "react-router-dom"; // 提前mock react-router-dom,确保组件导入时就使用mock版本 jest.mock("react-router-dom", () => ({ ...jest.requireActual("react-router-dom"), useHistory: jest.fn() })); describe("ReviseAction", () => { const pushMock = jest.fn(); beforeEach(() => { // 每次测试前重置mock,避免测试用例间的调用记录污染 pushMock.mockClear(); // 将pushMock关联到useHistory的返回值 useHistory.mockReturnValue({ push: pushMock }); }); it("点击按钮触发history.push", () => { render( <Router> <ReviseAction plans={[]} template={{}} coveragePercentage="12" territoryName="Name" existingTemplateId="1234" /> </Router> ); // 用getByTestId替代queryByTestId,找不到元素时直接报错,更容易定位问题 fireEvent.click(screen.getByTestId("revise-button")); // 可选:验证push的调用参数是否符合预期 expect(pushMock).toHaveBeenCalledWith({ pathname: "/xxx", state: { plans: [], template: {}, coveragePercentage: "12", territoryName: "Name", existingTemplateId: "1234" } }); }); });
额外优化说明
- 使用
getByTestId替代queryByTestId:前者找不到元素会直接抛出错误,避免因元素未渲染导致的无意义测试通过 - 每次测试前重置mock:确保不同测试用例的调用记录互不干扰
- 验证
push的调用参数:让测试更严谨,确保跳转逻辑完全符合预期
内容的提问来源于stack exchange,提问作者Hasteq
相关产品推荐
相关产品推荐

