Reputation: 2140
I have a large pytest suite for a django project which uses plenty of mockers (unittest.mock, requests-mock and aioresponses) and a fake filesystem. I have set up the fake filesystem to use some directories which are required by django:
PROJECT_BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
fs.add_real_paths(
[
PROJECT_BASE_DIR,
os.path.dirname(django.__file__),
]
)
At random, mockers stop working. AssertionError: Expected 'some_mocked_method' to be called once. Called 0 times.
I recieve no other errors or warnings, just the above message. I cannot reproduce this in a minimal example, since it only occurrs on some executions, not every time. When it happens, the tests freeze and I cannot even wait for the test suite to finish. I run them in parallel with (see EDIT)pytest-xdist
and 8 workers, which might also play a part in the problem.
I do not even know where to start on this problem. Has anyone experienced something similar when using the combination betweek unittest.mock
and pyfakefs
?
Is there any alternative to pyfakefs
? I could not find anything similar.
Is there any reason why these two would even interfere?
Here are the package versions I'm using
pyfakefs==5.3.2
pytest==7.4.3
pytest-django==4.7.0
pytest-mock==3.12.0
pytest-xdist==3.5.0
EDIT
Finally, I did produce a minimal example: https://github.com/konnerthg/minimal_django_pyfakefs_unittest_mock
Am I missing something very simple and obvious? Or is this a bug?
EDIT 2
Here's the output after running pytest in the project linked above. After pytest -m without_fakefs
(this is a dummy test case which checks that the pytest setup is correct): 2 passed
, as expected.
But after running pytest -m with_fakefs
, i.e. the exact same test case, but with the fs
fixture, I receive:
___________________________________________________ test_fs_and_mocker[1] ____________________________________________________
client = <django.test.client.Client object at 0x7f1e94f7a850>
fs = <pyfakefs.fake_filesystem.FakeFilesystem object at 0x7f1e94f7bb90>, counter = 1
@pytest.mark.with_fakefs
@pytest.mark.parametrize("counter", range(2))
def test_fs_and_mocker(
client,
fs,
counter,
):
with unittest.mock.patch("mysite.views.foo") as mocker:
client.get("/foo/")
> mocker.assert_called()
.../minimal_django_pyfakefs_unittest_mock/mysite/tests/mysite/views_test.py:14:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <MagicMock name='foo' id='139769325143440'>
def assert_called(self):
"""assert that the mock was called at least once
"""
if self.call_count == 0:
msg = ("Expected '%s' to have been called." %
(self._mock_name or 'mock'))
> raise AssertionError(msg)
E AssertionError: Expected 'foo' to have been called.
/usr/lib/python3.11/unittest/mock.py:908: AssertionError
================================================== short test summary info ===================================================
FAILED tests/mysite/views_test.py::test_fs_and_mocker[1] - AssertionError: Expected 'foo' to have been called.
=================================== 1 failed, 1 passed, 2 deselected, 2 warnings in 0.25s ====================================
Note that the first case (i.e. the first execution of the same test) always succeeds. If I run it 10 times rather than 2, the first succeeds and the other 9 fail. Moreover, if I run the cases in parallel with xdist
and 8 workers, the first 8 succeed and everything thereafter fails.
I run Ubuntu 23.04, 64-bit, Kernel Version Linux 6.2.0-36-generic on a Lenovo IdeaPad 5 Pro 16ARH7 with an AMD Ryzen™ 7 6800HS Creator Edition × 16 processor. Python 3.11.4
Upvotes: 0
Views: 210