python - mock.patch 忽略完全导入函数的原因是什么?
问题描述
今天我意识到unittest.mock.patch
如何导入函数很重要。根据使用的mock.patch
呼叫工作方式或被忽略的方式。在 Python 中,我们通常导入一个函数:
- 导入语句,如
import os
or - 像这样的
from ... import ...
声明from os import system
如果我使用Amock.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:使用全功能 import 和 from-import
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
不修补第二个示例中的功能? - 第二个补丁不起作用是否有任何具体实施原因?
解决方案
当你这样做时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')
.
推荐阅读
- python - 如何在python中处理桶列表空的尝试和异常
- linux - Linux - 登录时未更新 PATH
- php - 为什么在我的 Livewire 组件中调用一个空函数会改变数据,使films_count 未定义?
- javascript - Vue 3 计算关键字(组合 API)
- swift - 带有 SpriteView 的项目运行但动画未在模拟器中显示
- ckeditor - 如何在 React Application 的 CKEditor5 中添加实时协作?
- pandas - 将数据框重塑为新的数据框
- typescript - 循环包含的数组
- javascript - 如何在单击 HTML 时将按钮的文本颜色更改为随机颜色?
- reactjs - 打开我的应用程序一次后,它会自动更新并打开自己的应用程序