python - 无法修补魔法属性
问题描述
我希望能够修补魔法属性。
我要测试的主文件是 FileUtil.py,其中包含 FileUtil 的类定义:
class FileUtil:
@logit(showArgs=True, showRetVal=True)
def exec_file_path(self) -> str:
"""
Get the full dir and file path we're executing from using __file__, or if not available (probably because you're using a Jupyter notebook)
use os.path.abspath.
"""
try:
logger.debug('exec_file_path is about to attempt accessing __file__.')
return __file__
except NameError as err:
logger.debug('Exception message: {msg}'.format(msg=err))
return abspath('')
我在 mockTest.py 中也有一个本地测试,其中包含一个 AltFileUtil 类。为了区分调用的是哪一个,fUtil 实例化了 AltFileUtil,而 gUtil 实例化了 FileUtil。
被测方法使用__file__
,但除此之外,使用absdir
.
from os.path import abspath
from unittest.mock import MagicMock, PropertyMock, patch
class AltFileUtil:
def exec_file_path(self) -> str:
"""
Get the full dir and file path we're executing from using __file__, or if not available (probably because you're using a Jupyter notebook)
use os.path.abspath.
"""
try:
return __file__
except NameError as err:
return abspath('')
fUtil = AltFileUtil()
print (f'Part 1. function returns: {fUtil.exec_file_path()}')
patches = ['__main__.AltFileUtil', 'mockTest.AltFileUtil', ]
for p in patches:
print (f'Using patch of {p}.')
with patch(p) as mockFUtil:
type(mockFUtil.return_value).__file__ = PropertyMock(return_value='mockfilename')
x = mockFUtil.exec_file_path()
try:
print (f'Success! Got {x.__file__}.')
except (ValueError, AttributeError, TypeError) as e:
print(f'Got a {type(e)} error: {e}')
from FileUtil import FileUtil
gUtil = FileUtil()
print (f'Part 2. Using function from FileUtil.py, which returns: {gUtil.exec_file_path()}')
patches = ['FileUtil.FileUtil', ]
for p in patches:
print (f'Using patch of {p}.')
with patch(p) as mockFUtil:
type(mockFUtil.return_value).__file__ = PropertyMock(return_value='mockfilename')
x = mockFUtil.exec_file_path()
try:
print (f'Success! Got {x.__file__}.')
except (ValueError, AttributeError, TypeError) as e:
print(f'Got a {type(e)} error: {e}')
输出是
C:\Users\Owner\PycharmProjects\Utilities\venv\Scripts\python.exe C:/Users/Owner/.PyCharm2019.2/config/scratches/mockTest.py
Part 1. function returns: C:/Users/Owner/.PyCharm2019.2/config/scratches/mockTest.py
Using patch of __main__.AltFileUtil.
Got a <class 'AttributeError'> error: __file__
Using patch of mockTest.AltFileUtil.
Part 1. function returns: C:\Users\Owner\.PyCharm2019.2\config\scratches\mockTest.py
Using patch of __main__.AltFileUtil.
Got a <class 'AttributeError'> error: __file__
Using patch of mockTest.AltFileUtil.
Got a <class 'AttributeError'> error: __file__
Part 2. Using function from FileUtil.py, which returns: C:\Users\Owner\PycharmProjects\Utilities\FileUtil.py
Using patch of FileUtil.FileUtil.
Got a <class 'AttributeError'> error: __file__
Got a <class 'AttributeError'> error: __file__
Part 2. Using function from FileUtil.py, which returns: C:\Users\Owner\PycharmProjects\Utilities\FileUtil.py
Using patch of FileUtil.FileUtil.
2019-10-08 07:42:13,797 DEBUG Entering exec_file_path.
Got a <class 'AttributeError'> error: __file__
2019-10-08 07:42:13,797 DEBUG >> 0. <FileUtil.FileUtil object at 0x03721230>
2019-10-08 07:42:13,797 DEBUG exec_file_path is about to attempt accessing __file__.
2019-10-08 07:42:13,797 DEBUG >> Return value is C:\Users\Owner\PycharmProjects\Utilities\FileUtil.py.
2019-10-08 07:42:13,797 DEBUG Exiting exec_file_path.
2019-10-08 07:42:13,797 DEBUG Entering exec_file_path.
2019-10-08 07:42:13,797 DEBUG >> 0. <FileUtil.FileUtil object at 0x02E64050>
2019-10-08 07:42:13,797 DEBUG exec_file_path is about to attempt accessing __file__.
2019-10-08 07:42:13,797 DEBUG >> Return value is C:\Users\Owner\PycharmProjects\Utilities\FileUtil.py.
2019-10-08 07:42:13,797 DEBUG Exiting exec_file_path.
Process finished with exit code 0
我认为它应该给我mockfilename
而不是属性错误。
解决方案
在patch()
查找对象的名称空间中修补对象很重要。查看文档中的补丁位置。
在您的情况下,这是因为该行
return __file__
不__file__
通过在实例上查找属性来解析名称。它在模块命名空间中解析。
因此,您需要将其修补到正确的位置(即在FileUtil
定义的模块上)。
推荐阅读
- python - 如何在散点图 cmap 上设置颜色条最小值和最大值?
- c++ - 使用 istringstream 和 istream_iterator 反转句子中的单词
- azure - SQL漏洞评估中的“VA2065 - 服务器级防火墙规则”怎么办?
- ruby-on-rails - RubyMine 中的错误:没有为项目配置 ruby 解释器
- codenameone - 访问 Tab 组件内的组件
- c - 这个递归函数如何返回正确答案?
- swift - UITableView 中的行插入问题
- azure - MSFT Azure 管道能否连接到 Bitbucket 作为源代码控制系统,然后构建构建工件并将其部署到本地服务器?
- javascript - JSF 没有正确调用 jQuery 函数
- java - 如何在 Android Studio Camera2 中获取设备相机分辨率