Pytest mock.patch 请求 AttributeError: does not have the attribute 'json'

问题描述 投票:0回答:2

我正在尝试使用

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}'")

python python-requests mocking pytest python-unittest
2个回答
1
投票

正如@LuísMöllmann 已经指出的那样,补丁是不正确的。实际用法是:

requests.get().json()

但是补丁是:

requests.get.return_value = {some dict}

这意味着

requests.get()
已经返回
{some dict}
然后在调用
.json()
时失败。

解决方案 1

必须在

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

0
投票

你的模拟返回一个字典,而不是像原始

requests.get
函数那样的响应对象:

@patch('requests.get',
       return_value={
           "version": "v1",
           "greeting": "Aloha 👋"
       }
       )

所以基本上,你在做:

{"version":"v1","greeting":"Aloha 👋"}.json()

因此错误:

'dict' 对象没有属性 'json'

© www.soinside.com 2019 - 2024. All rights reserved.