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

TypeScript+Jest登录测试中axios mock实现错误排查

Axios登录流程测试Mock失效问题排查

现有代码存在的3个核心错误

  • Mock对象未替换真实axios依赖:你手动编写的./mocks/axios只是一个普通JS模块,业务代码中import axios from 'axios'实际引入的还是npm包的真实axios,所有mock逻辑完全不会生效,请求会按真实逻辑发送。
  • mockResolvedValueOnce传参错误:该API的参数是接口调用时直接resolve的返回值,你当前传入了一个返回Promise的函数,实际调用axios.post()时拿到的返回值是这个函数本身,而非预期的响应对象,业务代码读取res.data时会直接抛出类型错误。
  • 测试用例逻辑缺失+状态污染:
    1. 第二个登录测试用例渲染App后默认停留在首页,没有先跳转至登录页就直接查找邮箱、密码输入框,会直接触发元素不存在的报错;
    2. 没有在测试执行前重置mock函数的调用记录和返回值,多个用例串行执行时会出现mock状态串扰;
    3. userEvent的点击、输入操作是异步行为,未加await会导致事件未完成执行就进入后续断言,容易出现超时误报。

修正方案

  1. 配置Jest依赖映射,替换真实axios
    在项目的jest配置文件(jest.config.js/jest.config.ts)中添加moduleNameMapper规则,让所有引入axios的地方都加载你编写的mock文件:
module.exports = {
  // 其他已有配置
  moduleNameMapper: {
    '^axios$': '<rootDir>/src/__tests__/mocks/axios.js' // 替换为你的mock文件实际路径
  }
}
  1. 修正axios.post的mock返回值写法
    去掉外层包裹的函数,直接传入要resolve的响应对象:
// 错误写法
// mockAxios.post.mockResolvedValueOnce(() => Promise.resolve({ data: {...} }))
// 正确写法
mockAxios.post.mockResolvedValueOnce({
  data: {
    data: {
      token: "abdb23231232jdsaWEDwdxaCDA",
      expiresIn: 100000,
      isEnabled: true,
      isLocked: false,
    },
  },
})
  1. 补全测试逻辑,添加mock重置
    在beforeEach钩子中添加mock重置逻辑,补全登录页跳转步骤,给所有userEvent操作加await:
beforeEach(() => {
  // 原有IntersectionObserver mock逻辑
  // 新增重置axios mock
  mockAxios.post.mockReset()
  mockAxios.get.mockReset()
});

test("login attempt", async () => {
  // 先定义mock返回值
  mockAxios.post.mockResolvedValueOnce({
    data: {
      data: {
        token: "abdb23231232jdsaWEDwdxaCDA",
        expiresIn: 100000,
        isEnabled: true,
        isLocked: false,
      },
    },
  });
  render(
    <Provider store={store}>
      <ThemeProvider theme={theme}>
        <BrowserRouter>
          <App />
        </BrowserRouter>
      </ThemeProvider>
    </Provider>
  );
  // 先跳转到登录页
  const loginLink = screen.getByRole("link", { name: /Login/i });
  await userEvent.click(loginLink);
  await screen.findByText(/Please login/i, { exact: false });

  const email = "something@email.com";
  const pw = "pass123";
  const username = screen.getByPlaceholderText(/enter email/i);
  const password = screen.getByPlaceholderText(/password/i);
  const submit = screen.getByRole("button", { name: /Login/i });
  // 所有交互操作加await等待执行完成
  await userEvent.click(username);
  await userEvent.type(username, email);
  await userEvent.click(password);
  await userEvent.type(password, pw);
  await userEvent.click(submit);

  const profile = await screen.findByRole(
    "link",
    { name: "Account" },
    { timeout: 2000 }
  );
  expect(profile).toBeInTheDocument();
});

如果你不想手动写mock文件,也可以直接在测试文件顶部使用jest.mock('axios')自动生成axios的mock对象,不需要额外创建mock文件,配置成本更低。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 06:57:28