React+TypeScript单元测试引入axios时React-testing-library报错求助
问题
在React+TypeScript项目中编写单元测试时,引入axios并使用jest.mock("axios")模拟请求后,运行测试出现报错。已尝试安装axios类型定义、配置Babel、在package.json中添加--transformIgnorePatterns "node_modules/(?!axios)/"配置,但问题仍未解决。
组件代码:
import axios from "axios"; import React, { FC, useEffect, useState } from "react"; import { IUser } from "../../types/IUsers"; const Users: FC = () => { const [users, setUsers] = useState<IUser[]>([]); useEffect(() => { getUsers(); }, [users]); const getUsers = async () => { try { const response = await axios.get( "https://jsonplaceholder.typicode.com/users/" ); const res = response.data; setUsers(res); } catch (error) { console.log(error); } }; return ( <div data-testid="users-wrapper"> {users.map((user) => ( <div>{user.name}</div> ))} </div> ); }; export default Users;
测试代码:
import React from "react"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import Users from "./Users"; import axios from "axios"; jest.mock("axios"); describe("Testing user component", () => { test("Show title", () => { render(<Users />); const usersWrapper = screen.getByTestId("users-wrapper"); expect(usersWrapper).toBeInTheDocument(); }); });
解决方案
1. 修复组件内的无限循环问题
你的useEffect依赖了users状态,每次调用setUsers更新状态时,都会重新触发useEffect调用getUsers,形成无限循环,这会导致测试超时或报错。修改useEffect的依赖项为空数组,确保只在组件挂载时执行一次:
useEffect(() => { getUsers(); }, []); // 移除users依赖
如果需要后续重新触发请求,可以将getUsers用useCallback包裹,按需添加依赖。
2. 正确配置axios的Mock类型与返回值
由于使用TypeScript,jest.mock("axios")生成的Mock对象需要明确类型,同时要模拟axios.get的返回值,避免测试中出现异步请求未处理的问题:
import React from "react"; import { render, screen } from "@testing-library/react"; import Users from "./Users"; import axios from "axios"; // 类型断言,告知TypeScript这是被Jest Mock的axios实例 const mockedAxios = axios as jest.Mocked<typeof axios>; describe("Testing user component", () => { // 每次测试前重置Mock,避免测试间的状态污染 beforeEach(() => { mockedAxios.get.mockReset(); }); test("Renders users wrapper and loads users", async () => { // 模拟axios.get的成功返回数据 mockedAxios.get.mockResolvedValue({ data: [{ id: 1, name: "Test User 1" }, { id: 2, name: "Test User 2" }] }); render(<Users />); // 等待异步请求完成并渲染用户列表 await screen.findByText("Test User 1"); const usersWrapper = screen.getByTestId("users-wrapper"); expect(usersWrapper).toBeInTheDocument(); // 验证axios.get被正确调用 expect(mockedAxios.get).toHaveBeenCalledTimes(1); expect(mockedAxios.get).toHaveBeenCalledWith("https://jsonplaceholder.typicode.com/users/"); }); });
3. 确保Jest正确转换axios模块
如果使用Create React App,需要在package.json的scripts中正确配置transformIgnorePatterns,注意转义引号:
{ "scripts": { "test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!axios)/\"" } }
如果是自定义Jest配置(jest.config.js),添加以下配置:
module.exports = { transform: { "^.+\\.(ts|tsx)$": "ts-jest", "^.+\\.(js|jsx)$": "babel-jest", }, transformIgnorePatterns: [ "node_modules/(?!axios)/" ], };
4. 确认类型依赖匹配
确保@types/axios的版本与安装的axios版本匹配,避免类型冲突:
npm install @types/axios@匹配axios的版本号 --save-dev
内容的提问来源于stack exchange,提问作者ARSync
相关产品推荐
相关产品推荐

