今天,我意识到导入函数对于unittest.mock.patch
很重要。根据使用的方式,mock.patch
调用可以工作或被忽略。在Python中,我们通常使用以下命令导入函数:
import os
或from ... import ...
之类的from os import system
语句如果我使用mock.patch
,import os
就像一个超级按钮,但是它
如果我修补from os import system
,将被忽略。
示例1:使用导入
import os
from unittest import mock
def echo():
os.system('echo "Hello"')
with mock.patch('os.system') as mocked:
print(mocked)
mocked.side_effect = Exception('Patch works!')
echo()
示例1的输出
<MagicMock name='system' id='140037358656760'>
Traceback (most recent call last):
File "/.../config/scratches/scratch_7.py", line 12, in <module>
echo()
File "/.../config/scratches/scratch_7.py", line 6, in echo
os.system('echo "Hello"')
File "/.../python3.5/unittest/mock.py", line 917, in __call__
return _mock_self._mock_call(*args, **kwargs)
File "/.../python3.5/unittest/mock.py", line 973, in _mock_call
raise effect
Exception: Patch works!
示例2:使用全功能导入和自导入
当我完全导入os.system
时,mock.patch
会忽略mocked.side_effect
。
from os import system
from unittest import mock
def echo():
system('echo "Hello"')
with mock.patch('os.system') as mocked:
print(mocked)
mocked.side_effect = Exception('Patching does not work!')
echo()
print('Patch was ignored!')
示例2的输出
<MagicMock name='system' id='139851175427376'>
Hello
Patch was ignored!
在两种情况下,我都没有收到错误,mock
可以找到os.system
作为有效路径。但是,在第二种情况下,该功能未正确打补丁。
mock.patch
不修补该函数?答案 0 :(得分:3)
执行from os import system
时,将获得一个名为system
的变量,该变量指向os.system
函数。稍后,您通过修补程序分配到os.system
的另一个函数,但是system
始终指向旧函数。这是以下原因起作用的相同原因:
tmp = a
a = b
b = tmp
在第一个示例中不会发生这种情况,因为在对os.system
进行模拟之前先对其进行引用。为了解决您的第二个示例,我将执行以下操作:
from os import system
from unittest import mock
def echo():
system('echo "Hello"')
with mock.patch('__main__.system') as mocked:
print(mocked)
mocked.side_effect = Exception('Patching does not work!')
echo()
print('Patch was ignored!')
这样,您可以确保对正确的引用进行修补。这是一个相当普遍的模式。如果echo
函数位于名为echo.py
的文件中,则补丁调用看起来像with mock.patch('echo.system')
。