Why this code works with mock and not with pytest-mock?

I found this snippet on SO:

@pytest.fixture()
def boto3_session_mock():
    with mock.patch("boto3.session.Session") as mock_session_class:
        mock_session_object = mock.Mock()
        mock_client = mock.Mock()
        secret = {"some": "secret"}
        mock_client.get_secret_value.return_value = {'SecretString': json.dumps(secret)}
        mock_session_object.client.return_value = mock_client
        mock_session_class.return_value = mock_session_object
        yield mock_session_class

And it works. I tried to substitute unittest.mock with mocker fixture of pytest-mock and it does not work. More specifically, mock_session_class is None.

  1. Why?
  2. At this point, what’s the purpose of pytest-mock?

This sounds like something you should specifically ask the pytest-mock team - from the general python community on this forum you are probably not going to get that helpful responses just because it’s unlikely that there are that many people here with enough subject matter knowledge on this topic.

1 Like

It seems from the documentation that the point of using pytest-mock is that it undoes the patch automatically at the end of the test, so you don’t need the with statement.

Judging by the unit tests for pytest-mock, it seems that mocker.patch returns the mock object directly:

def test_mocker_resetall(mocker: MockerFixture) -> None:
    listdir = mocker.patch("os.listdir", return_value="foo")
    # ... snipped ...
    assert listdir("/tmp") == "foo"

…unlike unittest.mock.patch which returns the context manager your code expects:

>>> from unittest.mock import patch
>>> listdir = patch("os.listdir", return_value="foo")
>>> listdir
<unittest.mock._patch object at 0x7ff1283d6c50>
>>> listdir("/tmp")
<function _patch.decorate_callable.<locals>.patched at 0x7ff127b85300>
>>> with listdir as mock:
...   mock("/tmp")
... 
'foo'

Try removing the with statement (which shouldn’t be needed if pytest-mock undoes the patch automatically) and using the the return value from mocker.patch directly:

    mock_session_class = mocker.patch("boto3.session.Session")
1 Like

Eheh, I just find the same googling right now. I’ll let you know if it works on Monday, but it should :slight_smile:

I tried and it worked. Anyway for my use case mock is just enough, so I avoided to add yet another test dep. Ty for the help.

1 Like