2

I'm using the pytest-mock wrapper with pytest.

I can't get a PropertyMock to work with the requests package.

Here's an example of a function I'm trying to unit test:

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

And here's my attempt at a unit test:

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

The test fails because 200 is not returned by response.status_code.

I tried putting a PDB breakpoint after the requests.get() call, and checked the response.status_code attribute myself in PDB. I get a MagicMock object:

(Pdb) response.status_code
<MagicMock name='mock().status_code' id='4487925656'>
Daryl Spitzer
  • 143,156
  • 76
  • 154
  • 173

1 Answers1

1

It's the return value of a requests.get call which is assigned to response variable.

In this line:

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

You replaced the get method itself with a mock. But what you probably wanted was to replace it with something which returns your response mock when called, for example:

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

As an aside, consider using existing pytest plugins/fixtures for this code. requests_mock and responses are both good choices. After pip install requests_mock, for example, your test could look like this instead:

def test_get_better(requests_mock):
    requests_mock.get("http://foo.bar/", text="xyz")
    response_text = my_module.get()
    assert response_text == "xyz"
wim
  • 338,267
  • 99
  • 616
  • 750
  • Thank you! Changing the line to `monkeypatch.setattr(requests, 'get', lambda url: response_mock)` allows the test to pass. Please add this to your answer and I'll accept it. – Daryl Spitzer May 13 '19 at 16:29
  • 1
    OK, I added the monkeypatch to this answer. However, since I think using a requests mock fixture is a much better approach here, I also added an example of how to do that. – wim May 13 '19 at 19:03