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
相关产品推荐
相关产品推荐

