Proper way to return mocked object using pytest.fixture
Solution 1
The problem is that when the worker returns the scope of "with" statement ends making the object take its real value, the solution is to use "yield".
@pytest.fixture()
def mocked_worker():
with patch('test.test_module.os.getcwd', return_value="Testing"):
result = Worker()
yield result
Solution 2
I would recommend to use pytest-mock. So full example of one file (test_file.py) solution using this library would be:
import os
import pytest
from unittest.mock import patch
class Worker:
def work_on(self):
path = os.getcwd()
print(f'Working on {path}')
return path
@pytest.fixture()
def mocked_worker(mocker): # mocker is pytest-mock fixture
mocker.patch('test_file.os.getcwd', return_value="Testing")
def test_work_on(mocked_worker):
worker = Worker() # here we create instance of Worker, not mock itself!!
ans = worker.work_on()
assert ans == "Testing"
used libraries for reference:
pytest==5.3.0
pytest-mock==1.12.1
Bryan Cheng
Updated on June 11, 2022Comments
-
Bryan Cheng almost 2 years
I'm trying to setup the target under test in
@pytest.fixture
and use it in all my tests in the module. I'm able to patch the test correctly, but after I add the@pytest.fixture
to return the mock object and invoke the mocked object in other unit tests the object starting to refer back to the original function.Following is the code I have. I was expecting the
mocked_worker
in the unit test to refer to the return value, but it is invoking the actualos.getcwd
method instead.Please help me correct the code:
import os import pytest from unittest.mock import patch class Worker: def work_on(self): path = os.getcwd() print(f'Working on {path}') return path @pytest.fixture() def mocked_worker(): with patch('test.test_module.os.getcwd', return_value="Testing"): result = Worker() return result def test_work_on(mocked_worker): ans = mocked_worker.work_on() assert ans == "Testing"