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

Jest+React测试API调用报错:无法读取undefined的json属性

解决Jest Mock Fetch时的Cannot read properties of undefined (reading 'json')错误

问题重现

测试React组件MyButton时,为验证点击按钮触发的API调用,Mock了全局fetch方法,但运行测试时出现如下报错:

console.log
API call failed TypeError: Cannot read properties of undefined (reading 'json')

相关代码如下:

MyButton.js

const MyButton = ({ incrementFn, decrementFn }) => {
    const apiFunction = async () => {
        const dataToSend = { key: 'value' };
        try {
            const response = await fetch('https://api.example/data', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(dataToSend),
            });
            const data = await response.json();
            console.log(data);
            return data;
        } catch (error) {
            console.log('API call failed', error);
        }
    };

    return (
        <div>
            <button onClick={apiFunction} data-testid="apiButton">API</button>
            <h1>value</h1>
        </div>
    )
};

export default MyButton;

原测试代码(button.test.js)

import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import MyButton from './MyButton'

const fakeData = {
    name: "Joni Baez",
    age: "32",
    address: "123, Charming Avenue"
};

global.fetch = jest.fn().mockImplementation(() => {
    Promise.resolve({
        ok: true,
        json: () => Promise.resolve(fakeData),
    })
});


afterEach(() => {
    jest.clearAllMocks();
});

describe('<MyButton/>', () => {
    it('calls API mock', async () => {
        render(<MyButton/>);

        const apiButton = screen.getByTestId('apiButton');
        fireEvent.click(apiButton);
        
        await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1));

        expect(fetch).toHaveBeenCalledWith('https://api.example/data', expect.objectContaining({
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
        }));
    })
})

错误原因

你的fetch Mock实现存在问题:mockImplementation中的函数没有返回Promise对象,导致await fetch(...)得到的结果是undefined,后续调用response.json()自然会抛出“读取undefined的json属性”的错误。

修复方法

有两种简单的修复方式:

方式1:给Mock函数添加return语句

在mockImplementation的函数里返回Promise.resolve的对象:

global.fetch = jest.fn().mockImplementation(() => {
    // 加上return,返回Promise对象
    return Promise.resolve({
        ok: true,
        json: () => Promise.resolve(fakeData),
    })
});

方式2:使用mockResolvedValue简化Mock

Jest提供了mockResolvedValue方法,可以更简洁地Mock异步函数的返回值:

global.fetch = jest.fn().mockResolvedValue({
    ok: true,
    json: () => Promise.resolve(fakeData),
});

修复后的完整测试代码

import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import MyButton from './MyButton'

const fakeData = {
    name: "Joni Baez",
    age: "32",
    address: "123, Charming Avenue"
};

// 使用mockResolvedValue简化Mock实现
global.fetch = jest.fn().mockResolvedValue({
    ok: true,
    json: () => Promise.resolve(fakeData),
});


afterEach(() => {
    jest.clearAllMocks();
});

describe('<MyButton/>', () => {
    it('calls API mock', async () => {
        render(<MyButton/>);

        const apiButton = screen.getByTestId('apiButton');
        fireEvent.click(apiButton);
        
        await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1));

        expect(fetch).toHaveBeenCalledWith('https://api.example/data', expect.objectContaining({
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
        }));

        // 可选:验证response.json()是否被调用
        const mockResponse = await fetch();
        expect(mockResponse.json).toHaveBeenCalled();
    })
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 13:50:05