Jest测试中Mock axios get返回undefined问题排查
Jest Mock Service后响应返回undefined问题排查
我在Jest测试中Mock了Service的getResults方法,但组件调用后response返回undefined,不清楚问题出在哪,相关代码如下:
调用axios的组件代码
import {AgGridReact} from "ag-grid-react"; import React, {useEffect, useState, useMemo} from 'react'; useEffect(() => { if(searchObject) console.log("new being fetched") fetchResults(gridApi); }, [searchObject]); const fetchResults = (paramsApi) => { Service() .getResults(searchObject) .then((response) => { console.log("calling.....", response); // response为undefined,原因? let results = response.data.results; // 后续代码省略
Jest测试代码
import * as React from 'react'; import { screen } from '@testing-library/dom'; import { render } from '@testing-library/react'; import AgGridResults from "./AgGridResults"; describe('AgGridResults', () => { beforeEach(async () => { jest.mock("../../service/Service", () => ({ __esModule: true, default: () => ({ getResults: async () => ({ data: { results: { M0: { value: ["Source ID"] } } }, }), }), })); render(<AgGridResults searchObject={...} />); await waitFor(() => expect(screen.getByText('Actions')).toBeInTheDocument()) }); test('AgGridResults', () => { expect(screen.getByText('Actions')).toBeInTheDocument(); }); });
Service代码
import axios from 'axios'; import UrlUtility from './urlUtility'; function Service() { return { getResults: async (searchObject) => { let urlString = UrlUtility().convert(searchObject); if (searchObject && urlString) { return await axios.get('/api/' + urlString + '&pageLength=50'); } }, getAgreementTypes: async (searchTerm) => { return await axios.get('/api/' + 'searchString=' + searchTerm); }, }; } export default Service;
问题原因
- jest.mock的位置错误:jest.mock是静态语法,会在测试文件执行的最早期(所有import语句之前)被处理,放在beforeEach里不会生效。当你在beforeEach里调用jest.mock时,组件已经在测试文件顶部import时加载了原始的Service模块,后续的mock无法覆盖。
- searchObject可能无效:测试中传入的
searchObject={...}如果是无效值(比如空对象或未正确初始化),会导致Service的getResults方法中if (searchObject && urlString)判断不通过,方法返回undefined,即使mock了也可能因为分支问题没走到返回逻辑。
解决方案
1. 调整jest.mock的位置
把jest.mock移到测试文件的最顶部,确保在导入组件之前就完成mock:
import * as React from 'react'; import { screen, waitFor } from '@testing-library/react'; // 提前mock Service,确保组件导入时用的是mock版本 jest.mock("../../service/Service", () => ({ __esModule: true, default: () => ({ getResults: async () => ({ data: { results: { M0: { value: ["Source ID"] } } }, }), }), })); import AgGridResults from "./AgGridResults"; describe('AgGridResults', () => { beforeEach(async () => { // 传入有效的searchObject,避免Service分支判断不通过 render(<AgGridResults searchObject={{ key: 'value' }} />); await waitFor(() => expect(screen.getByText('Actions')).toBeInTheDocument()) }); test('AgGridResults renders correctly', () => { expect(screen.getByText('Actions')).toBeInTheDocument(); }); });
2. 若需动态mock(可选)
如果需要在不同测试用例中使用不同的mock,可以用jest.doMock配合require重新导入组件:
import * as React from 'react'; import { screen, waitFor } from '@testing-library/react'; describe('AgGridResults', () => { beforeEach(async () => { jest.doMock("../../service/Service", () => ({ __esModule: true, default: () => ({ getResults: async () => ({ data: { results: { M0: { value: ["Source ID"] } } }, }), }), })); // 重新导入组件,确保使用最新的mock const AgGridResults = require("./AgGridResults").default; render(<AgGridResults searchObject={{ key: 'value' }} />); await waitFor(() => expect(screen.getByText('Actions')).toBeInTheDocument()) }); test('AgGridResults renders correctly', () => { expect(screen.getByText('Actions')).toBeInTheDocument(); }); });
内容的提问来源于stack exchange,提问作者user21476047
相关产品推荐
相关产品推荐

