使用Jest测试时react-router-dom的useNavigate未被调用问题排查
组件登录提交逻辑
... const navigate = useNavigate(); ... const onSubmit = async (event) => { event.preventDefault(); const { payload } = await dispatch( startLoginWithEmail({ email, password }) ); if (payload.ok) { navigate("/", { replace: true, }); } } ...
单元测试代码
test("should call startLoginWithEmail when the Login button is clicked", () => { const email = "email@example.com"; const password = "12345678"; render( <Provider store={store}> <MemoryRouter> <Login /> </MemoryRouter> </Provider> ); mockStartLoginWithEmail.mockResolvedValue({ payload: { ok: true } }); const emailInputText = screen.getByRole("textbox", { name: /email/i }); fireEvent.change(emailInputText, { target: { name: "email", value: email }, }); const passwordInputText = screen.getByLabelText(/password/i); fireEvent.change(passwordInputText, { target: { name: "password", value: password }, }); const form = screen.getByRole("form"); fireEvent.submit(form); expect(mockStartLoginWithEmail).toHaveBeenCalledWith({ email, password }); expect(mockUseNavigate).toHaveBeenCalledWith("/", { replace: true, }); });
useNavigate的Mock实现
const mockUseNavigate = jest.fn(); jest.mock("react-router-dom", () => ({ ...jest.requireActual("react-router-dom"), useNavigate: () => mockUseNavigate, }));
问题现象
组件在应用中运行正常,但单元测试里mockUseNavigate始终显示调用次数为0。调试日志显示navigate逻辑应该被执行,但测试断言不通过。此前类似Mock方案在其他项目中有效。
修复方案
1. 等待异步操作完成
onSubmit是异步函数,fireEvent.submit不会等待内部异步逻辑执行完毕,导致断言时navigate还未被调用。有两种解决方式:
方式一:使用waitFor包裹断言
import { waitFor } from '@testing-library/react'; // 在fireEvent.submit之后添加: await waitFor(() => { expect(mockUseNavigate).toHaveBeenCalledWith("/", { replace: true }); });
方式二:改用userEvent处理提交
@testing-library/user-event会自动等待异步操作完成,更贴近真实用户行为:
import userEvent from '@testing-library/user-event'; // 替换fireEvent.submit为: await userEvent.submit(form); // 之后直接断言即可 expect(mockUseNavigate).toHaveBeenCalledWith("/", { replace: true });
2. 确认Mock的正确性
当前Mock写法本身没问题,但需确保:
mockUseNavigate在测试前被正确初始化,且每次测试后被重置(可在beforeEach中调用mockUseNavigate.mockClear())- 组件中
useNavigate的导入路径与Mock的react-router-dom一致,没有使用别名或相对路径导入
内容的提问来源于stack exchange,提问作者manou
相关产品推荐
相关产品推荐

