Reputation: 3086
In conftest (in an autouse fixture):
monkeypatch.setattr('collector.util.download_data', lambda url:"Winning" )
In collector/util.py:
def download_data(url):
assert False
In the_caller.py:
from collector.util import download_data
def some_function():
download_data("blah")
When I call some_function(), I get the assert. However, if I change the_caller.py to:
import collector
def some_function():
collector.util.download_data("blah")
then I get "Winning".
Why is this behaving differently, and how can I make the monkeypatch work for both scenarios?
Upvotes: 15
Views: 11448
Reputation: 3086
In general, it seems that the issue relates to how imports work in python. I'm not sure that there is a good solution.
The best work-around that I have found so far is the following:
monkeypatch.setattr('collector.util.download_data.__code__', replacement_function.__code__)
This works with both import types. One limitation is that this doesn't work with closures.
This functionality can be added to the framework via:
from _pytest.monkeypatch import monkeypatch
monkeypatch.setcode = lambda self, func_str, replacement_func: \
monkeypatch.setattr(self, func_str + ".__code__", replacement_func.__code__)
Reference: https://mail.python.org/pipermail/pytest-dev/2013-October/002386.html
Upvotes: 17