python 模拟 : @wraps(f) problems

标签 python python-2.7 unit-testing mocking functools

我想测试我写的一个简单的装饰器:

看起来像这样:

#utilities.py
import other_module
def decor(f):
    @wraps(f)
    def wrapper(*args, **kwds):
            other_module.startdoingsomething()
        try:
            return f(*args, **kwds)
        finally:
            other_module.enddoingsomething()
    return wrapper

然后我使用 python-mock 测试它:

#test_utilities.py
def test_decor(self):
    mock_func = Mock()
    decorated_func = self.utilities.decor(mock_func)
    decorated_func(1,2,3)
    self.assertTrue(self.other_module.startdoingsomething.called)
    self.assertTrue(self.other_module.enddoingsomething.called)
    mock_func.assert_called_with(1,2,3)

但它反击:

Traceback (most recent call last):
  File "test_utilities.py", line 25, in test_decor
    decorated_func = Mock(wraps=self.utilities.decor(mock_func))
  File "utilities.py", line 35, in decor
    @wraps(f)
  File "/usr/lib/python2.7/functools.py", line 33, in update_wrapper
    setattr(wrapper, attr, getattr(wrapped, attr))
  File "/usr/local/lib/python2.7/dist-packages/mock.py", line 660, in __getattr__
    raise AttributeError(name)
AttributeError: __name__

我知道 functools.wraps() 只是一个辅助包装器。因此,如果我将其取出,则测试有效。

我可以让 Mock 与 functools.wraps() 配合使用吗?

python 2.7.3

最佳答案

只要给你的模拟那个属性:

mock_func.__name__ = 'foo'

原来如此。

演示:

>>> from functools import wraps
>>> from mock import Mock
>>> def decor(f):
...     @wraps(f)
...     def wrapper(*args, **kwds):
...         return f(*args, **kwds)
...     return wrapper
... 
>>> mock_func = Mock()
>>> decor(mock_func)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in decor
  File ".../opt/lib/python2.7/functools.py", line 33, in update_wrapper
    setattr(wrapper, attr, getattr(wrapped, attr))
  File ".../lib/python2.7/site-packages/mock.py", line 660, in __getattr__
    raise AttributeError(name)
AttributeError: __name__
>>> mock_func.__name__ = 'foo'
>>> decor(mock_func)
<function foo at 0x10c4321b8>

设置 __name__ 完全没问题; @wraps 装饰器简单地将 __name__ 属性复制到包装器,并且在函数对象上,该属性通常设置为字符串值。在任何情况下,它都是函数的可写属性,只要您使用字符串,function.__name__ 就可以设置为任何值。

关于 python 模拟 : @wraps(f) problems,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22204660/

相关文章:

Python - isinstance 返回 false

python - 是否可以使用 pytest 测试 while True 循环(我尝试超时)?

javascript - 一个失败的测试会导致其他异步测试失败

unit-testing - 找不到Gradle命令行 Assets 中的Libgdx测试

python - 如何在声音设备中停止stream.write函数

python - 从字典列表中删除键值对

python - 如何从 python 中的 tzfile 中查找时区名称

python - 使用 matplotlib.pyplot 从 csv 中绘制数据

python - 如何使用 Python 3 将照片上传到 Facebook

python - 如何获取一个列表并以随机顺序打印所有内容,并在 python 中打印每个内容一次?