I am totally new to pytest-mock
. My project layout looks like this:
src
pull
app.py
utils
sftp.py
tests
test_pull.py
In app.py
I have this:
from src.utils.sftp import list_files
def handler():
response = list_files()
In sftp.py
I have this:
def list_files():
...
Trying to write a pytest which has list_files
mocked.
from src.pull.app import handler
def test_pulling(mocker):
mocker.patch('src.utils.sftp.list_files', return_value=["something"])
This however does not work because, I believe because the import inside app.py
is evaluated first. It works, when I change app.py
and do a local import.
def handler():
from src.utils.sftp import list_files
response = list_files()
Is there a better way to set this up? Ideally I don't want to be dependant on the import order - another developer might revert the local import and break the test.
Reloading the module will work and won't require other changes
def test_pulling(monkeypatch):
monkeypatch.setattr(src.utils.sftp, 'list_files', MagicMock(return_value="mock"))
importlib.reload(src.pull.app)
assert handler() == "mock"
however, sometimes it's an indication that you may need to refactor and use some dependency injection, like
def handler(lf=None):
response = lf() if lf else list_files()
return response
and the test would be as simple as
def test_pulling_2():
assert handler(MagicMock(return_value="mock2")) == "mock2"