I am working with a very large project and there are already a lot of test that use pytest
's monkeypatch
fixture. I wish to patch a specific method from a class which belongs to an imported module for example:
from project.common import services
in the services package there is a class with a method I wish to patch for example:
services.utils.Calculations.get_area()
I try to mock
and monkeypatch
it:
mocked_get_area_method= Mock(return_value=500)
monkeypatch.setattr(
'services.utils.Calculations.get_area',
mocked_get_user_ip_method,
)
then I create an object in my test:
class TestCommon:
def test_calculations(self,monkeypatch):
mocked_get_area_method= Mock(return_value=500)
monkeypatch.setattr(
'services.utils.Calculations.get_area',
mocked_get_user_ip_method,
)
calculations = services.utils.Calculations()
calculations.get_area()
mocked_get_user_ip_method.assert_called_once()
but I get an error saying: ModuleNotFoundError: No module named 'services'.
I believe the error comes form the fact that maybe monkeypatch
looks for objects starting from the high level main project folder. If i try to monkeypath
with this path:
monkeypatch.setattr(
'project.common.services.utils.Calculations.get_area',
mocked_get_user_ip_method,
)
the monkeypatching works BUT then I dont get a True
in my assert
because I believe the monkeypatching has changed the object in the main projects but since I have already imported it and instantiate the services.utils.Calculations()
from the locally imported module the patching does not work.
How can I make this work?
Note: The pytest is run from the main project directory.
You need to apply the patch to the module that has the from project.common import services
statement. So for example, assume I have a file project/frontend.py
that looks like this:
from project.common import services
def a_method():
calc = services.utils.Calculations()
return calc.get_area()
I'd like to test that a_method
correctly returns whatever value it receives from the get_area()
call, so in tests/test_frontend.py
I might write:
import project.frontend
from unittest import mock
def test_a_method(monkeypatch):
fake_get_area = mock.Mock(return_value=2.0)
monkeypatch.setattr(
project.frontend.services.utils.Calculations, "get_area", fake_get_area
)
res = project.frontend.a_method()
assert res == 2.0
Here, we're patching project.frontend.services.utils.Calculations
because we've imported project.frontend
and frontend.py
imports the project.common.services
as the name services
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.