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

Pytest使用mock.patch模拟requests时报AttributeError无'json'属性如何解决

错误原因

你当前为requests.get打桩时直接返回了Python字典对象,而真实场景下requests.get返回的是requests.Response类实例,只有该实例才内置了json()方法用于解析响应内容。你返回的字典没有json()属性,调用时自然抛出AttributeError。删除.json()后相当于直接返回mock的字典,不会触发方法调用所以能跑通,但不符合业务代码的逻辑要求。

修复方案

你只需将mock返回值改为带json()方法的响应对象即可,推荐使用unittest.mock.Mock来快速构造,修改后的测试代码如下:

from unittest.mock import patch, Mock
from src.foo_helper import get_foo_data

@patch('requests.get')
def test_get_foo_data(mock_get):
    # 构造模拟的响应对象,配置其json方法的返回值
    mock_response = Mock()
    mock_response.json.return_value = {
        "version": "v1",
        "greeting": "Aloha 👋"
    }
    # 让mock的requests.get返回上面构造的响应对象
    mock_get.return_value = mock_response

    result = get_foo_data(
        'route', 'key', 'password'
    )
    # 断言返回结果符合预期
    assert result == {
        "version": "v1",
        "greeting": "Aloha 👋"
    }
    # 可选:验证requests.get被正确调用,参数符合预期
    mock_get.assert_called_once_with('route', auth=('key', 'password'))
你原有测试代码的其他问题
  • 测试函数多了mock_json参数:你只@patch了requests.get一个对象,pytest只会注入1个mock参数,多余参数会导致测试启动失败
  • 代码中get_open_play_data变量未定义,属于多余内容可以删除
  • 原有断言assert mock_get() == result逻辑错误:mock_get()调用后返回的是响应对象,和response.json()的返回值(字典)不可能相等,直接和预期字典对比即可
可选实现方案

如果你想使用真实的Response对象做mock,也可以用requests自带的Response类构造:

from unittest.mock import patch
from requests.models import Response
from src.foo_helper import get_foo_data

@patch('requests.get')
def test_get_foo_data(mock_get):
    mock_response = Response()
    mock_response.status_code = 200
    # 把返回的字典转成JSON字节串赋值给_content属性
    mock_response._content = b'{"version": "v1", "greeting": "Aloha 👋"}'
    mock_get.return_value = mock_response

    result = get_foo_data('route', 'key', 'password')
    assert result == {"version": "v1", "greeting": "Aloha 👋"}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 00:42:00