如何用Jest覆盖React/TypeScript中try块内axios请求后的代码?
解决try块内axios请求后代码未被测试覆盖的问题
问题根源分析
你遇到的问题核心来自两个点:
- 你mock的是
axios.post,但原代码调用的是直接调用axios函数(axios({method: "post", ...})),两者调用入口不同,导致mock未生效 - mock响应数据的结构和原代码预期不匹配,
res.data.data会变为undefined,触发后续代码报错进入catch块
具体修复步骤
1. 修正axios的mock方式
原代码使用axios通用请求方式,需要mock整个axios函数而非axios.post方法:
import axios from 'axios'; // 全局mock axios模块 jest.mock('axios'); const mockedAxios = axios as jest.Mocked<typeof axios>; // 在测试用例中设置成功响应 mockedAxios.mockResolvedValueOnce(mockResponse);
或用spyOn方式局部mock:
const axiosSpy = jest.spyOn(axios, 'request').mockResolvedValueOnce(mockResponse);
2. 调整mock响应数据的结构
原代码读取的是res.data.data,你的mockResponse需要包含两层data嵌套:
const mockResponse = { data: { data: { // 新增这一层data,匹配原代码的res.data.data user: { id: 1, name: "user", email: "user@mail.com", email_verified_at: null, created_at: "2022-12-27T17:10:23.000000Z", updated_at: "2022-12-27T17:10:29.000000Z", deleted_at: null, last_login_at: "2022-12-27T17:10:29.301355Z", roles: ["user"], }, token: { access_token: "1|Buc8kgCTGFzHdS2HU11ZmWS30SEXHEiLCEQGbBnH", token_type: "Bearer", }, }, }, };
3. 确保依赖函数无报错
buildUserData、saveUserData、login这些函数如果抛出错误,会直接进入catch块,需提前mock:
// 假设这些函数是外部导入的,按需mock import { buildUserData, saveUserData } from './user-utils'; import { login } from './auth-service'; import { useNavigate } from 'react-router-dom'; jest.mock('./user-utils', () => ({ buildUserData: jest.fn(() => ({ name: "user", email: "user@mail.com", roles: ["user"], token: "1|Buc8kgCTGFzHdS2HU11ZmWS30SEXHEiLCEQGbBnH" })), saveUserData: jest.fn() })); jest.mock('./auth-service', () => ({ login: jest.fn(() => Promise.resolve()) })); // 组件内的navigate需mock useNavigate jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useNavigate: jest.fn(() => jest.fn()) }));
4. 测试时等待异步函数完成
logUser是异步函数,测试必须用await确保所有异步操作执行完毕:
test('logUser should execute success flow', async () => { // 准备mock数据和函数 // ... // 调用logUser并等待完成 await logUser(); // 验证后续函数调用 expect(buildUserData).toHaveBeenCalled(); expect(saveUserData).toHaveBeenCalled(); expect(setDismissAlert).toHaveBeenCalledWith(true); });
额外检查点
- 确认
localStorage.getItem("i18nextLng")在测试环境有值,或mocklocalStorage避免报错 - 检查代码覆盖工具配置,确保未排除目标代码行
内容的提问来源于stack exchange,提问作者Jozias Martini
相关产品推荐
相关产品推荐

