如何在pytest单元测试中使用PropertyMock返回请求响应属性?

时间:2019-05-10 23:54:18

标签: python python-requests pytest pytest-mock

我在pytest中使用pytest-mock wrapper

我无法使用PropertyMock与requests package一起使用。

这是我要进行单元测试的功能的示例:

def get():
    url = f'http://foo.bar/'
    response = requests.get(url)
    if response.status_code != 200:
        sys.exit(1)
    return response.text

这是我进行单元测试的尝试:

import pytest
import my_module
import requests

def test_get(mocker, monkeypatch):
    response_mock = mocker.MagicMock()
    status_code_mock = mocker.PropertyMock(return_value=200)
    text_mock = mocker.PropertyMock(return_value='xyz')
    type(response_mock).status_code = status_code_mock
    type(response_mock).text = text_mock
    monkeypatch.setattr(requests, 'get', response_mock)

    my_module.get()

测试失败,因为response.status_code未返回200。

我尝试在requests.get()调用之后放置一个PDB断点,并亲自在PDB中检查了response.status_code属性。我得到了一个MagicMock对象:

(Pdb) response.status_code
<MagicMock name='mock().status_code' id='4487925656'>

1 个答案:

答案 0 :(得分:1)

这是分配给requests.get变量的response调用的返回值

在这一行:

monkeypatch.setattr(requests, 'get', response_mock)

您用模拟代替了get方法本身。但是您可能想要的是将其替换为在调用时会返回您的响应模拟的内容,例如:

monkeypatch.setattr(requests, 'get', lambda url: response_mock)

此外,请考虑将现有的pytest插件/夹具用于此代码。 requests_mockresponses都是不错的选择。例如,在pip install requests_mock之后,您的测试可能看起来像这样:

def test_get_better(requests_mock):
    requests_mock.get("http://foo.bar/", text="xyz")
    response_text = my_module.get()
    assert response_text == "xyz"