You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用RTL异步测试React中的history.push路由跳转功能

问题根因
  • 没有mock异步依赖createAuthor:测试环境下没有真实的后端服务支撑这个接口调用,接口要么抛出异常要么永远处于pending状态,导致await createAuthor之后的跳转逻辑永远不会执行。
  • 没有等待异步逻辑执行完成就做断言:handleSave是异步函数,点击按钮后你没有等异步任务跑完就立刻校验跳转结果,此时跳转逻辑还没触发。另外你给history.length、history.location.pathname加await完全无效,这两个都是history对象的同步属性,不会等待异步逻辑执行。
修复方案
  1. 首先mockcreateAuthor方法,让它返回正常resolve的Promise,模拟接口调用成功的场景
  2. 点击按钮时等待异步事件执行完成,或者用waitFor包裹跳转断言,保证校验时异步逻辑已经跑完
  3. 移除history属性前无效的await

以下是修改后的完整测试代码:

import React from "react";
import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { createMemoryHistory } from "history";
import { Router } from "react-router-dom";
import { ROUTE_AUTHOR_LIST } from "../constants";
// 导入要mock的异步方法
import { createAuthor } from "../../services/authors";

// mock整个authors服务
jest.mock("../../services/authors", () => ({
  createAuthor: jest.fn().mockResolvedValue({ id: 1, name: '测试作者' })
}));

describe("Save button functionality", () => {
  test("redirect to correct URL", async () => {
    const history = createMemoryHistory();
    render(
      <Router history={history}>
        <AuthorCreate />
      </Router>
    );
    // 如果组件内没有对应heading可以删掉这行断言
    expect(
      screen.getByRole("heading", { name: /create author/i })
    ).toBeInTheDocument();

    const saveBtn = screen.getByRole("button", {
      name: /save/i,
      type: "button",
    });

    // userEvent.click本身支持await,等待事件触发的所有异步逻辑执行完成
    await userEvent.click(saveBtn);

    // 用waitFor包裹断言,保证跳转完成后再校验
    await waitFor(() => {
      expect(history.length).toBe(2); 
      expect(history.location.pathname).toBe(ROUTE_AUTHOR_LIST);
    })
    // 可额外加断言验证createAuthor是否被正确调用
    expect(createAuthor).toHaveBeenCalledTimes(1);
  });
})

内容的提问来源于stack exchange,提问作者kornavol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 20:45:11