How To Remove A Library With Monkeypatch Or Mock In Pytest?
Solution 1:
What I ended up doing that worked, and which I had confirmed was a reasonable method thanks to Anthony Sottile, was to mock that the extra dependency (here requests
) does not exist by setting it to None
in sys.modules
and then reloading the module(s) that would require use of requests
.
I test that there is an actual complaint that requests
doesn't exist to be imported by using caplog
.
Here is the test I'm currently using (with the names changed to match my toy example problem in the question above)
import mylib
import sys
import logging
import pytest
from unittest import mock
from importlib import reload
from importlib import import_module
# ...deftest_missing_contrib_extra(caplog):
with mock.patch.dict(sys.modules):
sys.modules["requests"] = Noneif"mylib.contrib.utils"in sys.modules:
reload(sys.modules["mylib.contrib.utils"])
else:
import_module("mylib.cli")
with caplog.at_level(logging.ERROR):
# The 2nd and 3rd lines check for an error message that mylib throwsfor line in [
"import of requests halted; None in sys.modules",
"Installation of the contrib extra is required to use mylib.contrib.utils.download",
"Please install with: python -m pip install mylib[contrib]",
]:
assert line in caplog.text
caplog.clear()
I should note that this is actually advocated in @Abhyudai's answer to "Test for import of optional dependencies in init.py with pytest: Python 3.5 /3.6 differs in behaviour" which @hoefling linked to above (posted after I had solved this problem but before I got around to posting this).
If people are interested in seeing this in an actual library, c.f. the following two PRs:
A note: Anthony Sottile has warned that
reload()
can be kinda iffy -- I'd be careful with it (things which have old references to the old module will live on, sometimes it can introduce new copies of singletons (doubletons? tripletons?)) -- I've tracked down many-a-test-pollution problems toreload()
so I'll revise this answer if I implement a safer alternative.
Post a Comment for "How To Remove A Library With Monkeypatch Or Mock In Pytest?"