我正在尝试使用
from unittest.mock import patch
测试 api 模拟调用。当我在我的函数的响应返回中包含AttributError
(即.json()
)时,我不断得到一个return response.json()
。
当我在返回语句中排除
.json()
时,测试通过。我对测试还很陌生,我不知道如何解决这个错误。有谁知道如何通过在退货声明中保留.json()
来解决这个问题?
这里是我的代码供参考:
test_pytest.py
from unittest.mock import patch
from src.open_play_helper import get_open_play_data
@patch('requests.get',
return_value={
"version": "v1",
"greeting": "Aloha 👋"
}
)
def test_get_open_play_data(mock_get, mock_json):
print("Mock_get: ", mock_get())
print("Mock_json: ", mock_json())
print("Function: ", get_open_play_data)
# print("Function call: ", get_open_play_data('https://connect.secretlyportal.com/v1/',
# OP_CONFIG['OP_KEY'],
# OP_CONFIG['OP_PASSWORD']))
result = get_open_play_data(
'route', 'key', 'password'
)
print("Result: ", result)
assert mock_get() == result
assert False
open_play_helper.py
import requests
def get_open_play_data(route, key, password) -> object:
# route should be a string
try:
response = requests.get(
route,
auth=(
key,
password
)
)
print("Response: ", response)
return response.json()
except requests.exceptions.RequestException as e:
print(f"There was a problem with your request: '{e}'")
正如@LuísMöllmann 已经指出的那样,补丁是不正确的。实际用法是:
requests.get().json()
但是补丁是:
requests.get.return_value = {some dict}
这意味着
requests.get()
已经返回 {some dict}
然后在调用 .json()
时失败。
必须在
requests.get.return_value.json.return_value
处嘲笑字典响应,而不仅仅是 requests.get.return_value
:
@patch('requests.get')
def test_get_open_play_data(mock_get):
mock_json = {
"version": "v1",
"greeting": "Aloha 👋"
}
mock_get.return_value.json.return_value = mock_json
result = get_open_play_data(
'route', 'key', 'password'
)
print("Result: ", result)
assert mock_json == result
不要重新发明模拟
requests
模块的轮子。使用诸如 requests_mock 之类的库,它可以为您轻松完成。
import requests_mock as requests_mock_lib
def test_get_open_play_data_using_lib(requests_mock):
mock_json = {
"version": "v1",
"greeting": "Aloha 👋"
}
requests_mock.get("http://route", json=mock_json) # If you want the mock to be used on any URL, replace <"http://route"> with <requests_mock_lib.ANY>
result = get_open_play_data(
'http://route', 'key', 'password'
)
print("Result: ", result)
assert mock_json == result
你的模拟返回一个字典,而不是像原始
requests.get
函数那样的响应对象:
@patch('requests.get',
return_value={
"version": "v1",
"greeting": "Aloha 👋"
}
)
所以基本上,你在做:
{"version":"v1","greeting":"Aloha 👋"}.json()
因此错误:
'dict' 对象没有属性 'json'