Date: 2021-11-25
Imagine we have following Python module:
mymodule/
somefunc.py
__init__.py
# somefunc.py
def somefunc():
pass
# __init__.py
from .somefunc import somefuncThe most obvious way to patch this would be:
from unittest.mock import patch
with patch("mymodule.somefunc.somefunc"):
...We”d immediately get an error:
Traceback (most recent call last):
File "test.py", line 4, in <module>
with patch("mymodule.somefunc.somefunc") as mock:
File "/Users/swen/.pyenv/versions/3.8.5/lib/python3.8/unittest/mock.py", line 1393, in __enter__
original, local = self.get_original()
File "/Users/swen/.pyenv/versions/3.8.5/lib/python3.8/unittest/mock.py", line 1366, in get_original
raise AttributeError(
AttributeError: <function somefunc at 0x107a969d0> does not have the attribute "somefunc"The next obvious step is to try to leave off the module name:
from unittest.mock import patch
with patch("mymodule.somefunc"):
...This doesn”t raise an error, but it doesnt” actually patch the
function. It ends up patching the somefunc module instead.
The only way to work around this is to use
unittest.mock.patch.object:
import sys
from unittest.mock import patch
with patch.object(sys.modules["mymodule.somefunc"], "somefunc"):
...This correctly patches the function and not the module.