The patch
function from the mock
library is sensitive to how things are imported. Is there a deep reason why I can't just use the fully qualified name where the function was originally defined regardless of how it is imported in other modules?
using a "module import" works fine
patch_example.py:
# WORKS!
from mock import patch
import inner
def outer(x):
return ("outer", inner.inner(x))
@patch("inner.inner")
def test(mock_inner):
mock_inner.return_value = "MOCK"
assert outer(1) == ("outer", "MOCK")
return "SUCCESS"
if __name__ == "__main__":
print test()
inner.py:
def inner(x):
return ("inner.inner", x)
Running python patch_example.py
just outputs success.
However, changing the import can have pretty dramatic consequences
Using a module alias still works
# WORKS!
from mock import patch
import inner as inner2
def outer(x):
return ("outer", inner2.inner(x))
@patch("inner.inner")
def test(mock_inner):
mock_inner.return_value = "MOCK"
assert outer(1) == ("outer", "MOCK")
return "SUCCESS"
if __name__ == "__main__":
print test()
directly importing the symbol, however, requires you to change the fully qualified name.
direct import, inner.inner
as fully qualified name.
# FAILS!
from mock import patch
from inner import inner
def outer(x):
return ("outer", inner(x))
@patch("inner.inner")
def test(mock_inner):
mock_inner.return_value = "MOCK"
assert outer(1) == ("outer", "MOCK")
return "SUCCESS"
if __name__ == "__main__":
print test()
produces
% python patch_example.py
Traceback (most recent call last):
File "patch_example.py", line 14, in <module>
print test()
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1305, in patched
return func(*args, **keywargs)
File "patch_example.py", line 10, in test
assert outer(1) == ("outer", "MOCK")
AssertionError
If I update the fully qualified path to patch_example.inner
, the patch still fails.
# FAILS!
from mock import patch
from inner import inner
def outer(x):
return ("outer", inner(x))
@patch("patch_example.inner")
def test(mock_inner):
mock_inner.return_value = "MOCK"
assert outer(1) == ("outer", "MOCK")
return "SUCCESS"
if __name__ == "__main__":
print test()
% python patch_example.py
Traceback (most recent call last):
File "patch_example.py", line 14, in <module>
print test()
File "/usr/local/lib/python2.7/site-packages/mock/mock.py", line 1305, in patched
return func(*args, **keywargs)
File "patch_example.py", line 10, in test
assert outer(1) == ("outer", "MOCK")
AssertionError
using __main__.inner
as my fully qualified name patches the right thing though.
# WORKS!
from mock import patch
from inner import inner
def outer(x):
return ("outer", inner(x))
@patch("__main__.inner")
def test(mock_inner):
mock_inner.return_value = "MOCK"
assert outer(1) == ("outer", "MOCK")
return "SUCCESS"
if __name__ == "__main__":
print test()
prints "SUCCESS"
So, why can't I patch the value of inner when it's imported as from inner import inner
using either the fully qualified name of the original symbol inner.inner
or the use the name of the main python module rather than __name__
?
Tested with Python 2.7.12 on OS X.