#python #unit-testing #mocking
Вопрос:
У меня есть вызванный пакет my_package
с одним модулем под названием my_module
:
$ tree my_package/
my_package/
├── __init__.py
├── my_module.py
├── my_module.py~
└── __pycache__
├── __init__.cpython-36.pyc
└── my_module.cpython-36.pyc
my_module
имеет функцию, называемую compute_something
:
$ cat my_package/my_module.py
def compute_something():
return 0
Я пытаюсь высмеять эту функцию в целях модульного тестирования:
$ cat mocks.py
import mock
from my_package import my_module
def unmocked():
print(my_module.compute_something())
@mock.patch('my_module.compute_something')
def mocked(mock_compute_something):
mock_compute_something.return_value = 1
print(my_module.compute_something())
unmocked()
mocked()
$ python mocks.py
0
Traceback (most recent call last):
File "mocks.py", line 14, in <module>
mocked()
File "/home/pcoccoli/.pyenv/versions/3.6.8/lib/python3.6/site-packages/mock/mock.py", line 1345, in patched
keywargs) as (newargs, newkeywargs):
File "/home/pcoccoli/.pyenv/versions/3.6.8/lib/python3.6/contextlib.py", line 81, in __enter__
return next(self.gen)
File "/home/pcoccoli/.pyenv/versions/3.6.8/lib/python3.6/site-packages/mock/mock.py", line 1325, in decoration_helper
arg = exit_stack.enter_context(patching)
File "/home/pcoccoli/.pyenv/versions/3.6.8/lib/python3.6/contextlib.py", line 330, in enter_context
result = _cm_type.__enter__(cm)
File "/home/pcoccoli/.pyenv/versions/3.6.8/lib/python3.6/site-packages/mock/mock.py", line 1398, in __enter__
self.target = self.getter()
File "/home/pcoccoli/.pyenv/versions/3.6.8/lib/python3.6/site-packages/mock/mock.py", line 1573, in <lambda>
getter = lambda: _importer(target)
File "/home/pcoccoli/.pyenv/versions/3.6.8/lib/python3.6/site-packages/mock/mock.py", line 1245, in _importer
thing = __import__(import_path)
ModuleNotFoundError: No module named 'my_module'
Как вы можете видеть, my_module
существует и находится просто отлично (я вызываю его из unmocked
функции, и вы можете видеть его вывод), если я не попытаюсь mock.patch
это сделать. Я не понимаю, почему это так.
Комментарии:
1. Я думаю, никто не хочет, чтобы над ним насмехались.
2. Я предполагаю, что декораторы вызывают эту функцию из другого файла, где my_module не распознан. Что происходит, когда вы помещаете инструкцию import внутри издевательской функции?
3. Не совсем понимаю, что ты имеешь в виду. Декоратор не вызывает функцию — он должен исправить ее в текущем пространстве имен.
4.
python @mock.patch('my_module.compute_something')
здесь метод path из класса mock вызывается в другом сеансе со строковой ссылкой на my_module.compute_something. Этот другой сеанс понятия не имеет, что или где это.5. не могли бы вы попытаться перейти
from my_package import my_module
наimport my_package
Ответ №1:
После перечитывания https://docs.python.org/3/library/unittest.mock.html#where-to-patch Я вижу, что это должно быть:
@mock.patch('mocks.my_module.compute_something')
Это потому, что я импортировал my_module
в mocks.py
. В моем коде в вопросе отсутствует ведущее «издевается». в target
.
Комментарии:
1. Разве это дурной тон-отвечать на свой собственный вопрос?