python-3.xpython-requestsmockingpytestmonkeypatching

How to assert a monkey patch was called in pytest?


Consider the following:

class MockResponse:
    status_code = 200

    @staticmethod
    def json():
        return {'key': 'value'}
                                  # where api_session is a fixture
def test_api_session_get(monkeypatch, api_session) -> None:
    def mock_get(*args, **kwargs):
        return MockResponse()

    monkeypatch.setattr(requests.Session, 'get', mock_get)
    response = api_session.get('endpoint/') # My wrapper around requests.Session
    assert response.status_code == 200
    assert response.json() == {'key': 'value'}
    monkeypatch.assert_called_with(
        'endpoint/',
        headers={
            'user-agent': 'blah',
        },
    )

How can I assert that the get I am patching gets called with '/endpoint' and headers? When I run the test now I get the following failure message:

FAILED test/utility/test_api_session.py::test_api_session_get - AttributeError: 'MonkeyPatch' object has no attribute 'assert_called_with'

What am I doing wrong here? Thanks to all those of who reply in advance.


Solution

  • You need a Mock object to call assert_called_with - monkeypatch does not provide that out of the box. You can use unittest.mock.patch with side_effect instead to achieve this:

    from unittest import mock
    import requests
    
    ...
    
    @mock.patch('requests.Session.get')
    def test_api_session_get(mocked, api_session) -> None:
        def mock_get(*args, **kwargs):
            return MockResponse()
    
        mocked.side_effect = mock_get
        response = api_session.get('endpoint/') 
        ...
        mocked.assert_called_with(
            'endpoint/',
            headers={
                'user-agent': 'blah',
            },
        )
    

    Using side_effect is needed to still get a mock object (mocked in this case, of type MagickMock), instead of just setting your own object in patch, otherwise you won't be able to use the assert_called_... methods.

    To clarify: when I write "monkeypatch does not provide that out of the box" this is related to the usage of the assert_called... methods. It does not imply that you can't use monkeypatch to implement a similar functionality, as is nicely shown in the answer by Tommy.