Как использовать PropertyMock для возврата атрибутов ответа на запросы в модульном тесте pytest? - PullRequest
2 голосов
/ 11 мая 2019

Я использую оболочку pytest-mock с pytest.

Я не могу заставить PropertyMock работать с пакетом запросов .

Вот пример функции, которую я пытаюсь выполнить модульным тестом:

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()

Тест не пройден, поскольку 200 не возвращается response.status_code.

Я попытался установить точку останова PDB после вызова requests.get() и сам проверил атрибут response.status_code в PDB. Я получаю объект MagicMock:

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

1 Ответ

1 голос
/ 11 мая 2019

Это возвращаемое значение вызова requests.get, которое назначено переменной response.

В этой строке:

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

Вы заменили сам метод get на макет. Но то, что вы, вероятно, хотели заменить на что-то, что возвращает ваш ответ при вызове, например:

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

В качестве отступления рассмотрите возможность использования существующих плагинов / приспособлений pytest для этого кода. requests_mock и responses - хороший выбор. Например, после 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"
...