假设我有一个简单的装饰方法,如下所示:
def my_decorator(fn):
def _wrapper(*args, **kwargs):
print 'Calling decorated function'
fn(*args, **kwargs)
return _wrapper
class Foo(object):
@my_decorator
def incr(self, x):
return x+1
装饰器“删除”方法签名以用于自动指定目的:
>>> mock_foo = mock.create_autospec(Foo, instance=True)
>>> mock_foo.incr(1, 2, 3, 4)
<MagicMock name='mock.incr()' id='23032592'>
这应该会提高:
TypeError: <lambda>() takes exactly 2 arguments (5 given)
由于关键字参数中的拼写错误,我遇到过这样的错误。
有什么方法可以编写装饰器(或给 autospec 一个“提示”)以便捕获这些类型的错误?
最佳答案
我认为 autospec 不能直接做到这一点。不过,您可以在装饰器中进行一些修改,以便可以测试未装饰的函数。如果您让装饰器保存对未装饰函数的引用:
def my_decorator(fn):
def _wrapper(*args, **kwargs):
print 'Calling decorated function'
fn(*args, **kwargs)
_wrapper._orig = fn
return _wrapper
您可以通过模拟的装饰函数访问它:
>>> mock_incr = mock.create_autospec(Foo.incr)
>>> mock_incr(1,3,4,5,5) # Decorated function doesn't fail.
<MagicMock name='mock()' id='8734864'>
>>> mock_incr._orig(1,3,4,5,5) # But the original does, which is what we want
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib64/python2.6/site-packages/mock.py", line 954, in __call__
_mock_self._mock_check_sig(*args, **kwargs)
TypeError: <lambda>() takes exactly 3 arguments (6 given)
>>> mock_incr._orig(1,3)
<MagicMock name='mock._orig()' id='8739664'>
但是,如果您自动指定整个实例,则这不起作用。不知道为什么。
>>> mock_foo = mock.create_autospec(Foo, instance=True)
>>> mock_foo.incr(1,3,4,5) # We expect this to not raise an exception
<MagicMock name='mock.incr2()' id='8758416'>
>>> mock_foo.incr._orig(1,3,4,5) # But we were hoping this would :(
<MagicMock name='mock.incr._orig()' id='8740624'>
还值得注意的是Venusian ,这可以改变装饰器绑定(bind)到装饰方法的方式,专门解决这个用例。不过,可能比您想要的更重量级。
关于python - Autospec "through"带有 unittest.mock 的装饰器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24042546/