Python Autospec mock未正确保留签名?
根据报告: 自动指定创建的模拟对象具有与其替换的对象相同的属性和方法,并且任何函数和方法(包括构造函数)具有与真实对象相同的调用签名。 但这似乎不是真的。Stdlib仍然在mock上看到一个通用的Python Autospec mock未正确保留签名?,python,unit-testing,mocking,inspect,Python,Unit Testing,Mocking,Inspect,根据报告: 自动指定创建的模拟对象具有与其替换的对象相同的属性和方法,并且任何函数和方法(包括构造函数)具有与真实对象相同的调用签名。 但这似乎不是真的。Stdlib仍然在mock上看到一个通用的*args、**kwargs签名: >>> from unittest.mock import patch >>> def foo(arg1, arg2, arg3): ... pass ... >>> print(*inspect
*args、**kwargs
签名:
>>> from unittest.mock import patch
>>> def foo(arg1, arg2, arg3):
... pass
...
>>> print(*inspect.signature(foo).parameters)
arg1 arg2 arg3
>>> with patch("__main__.foo", autospec=True) as mock:
... print(*inspect.signature(mock).parameters)
...
args kwargs
autospec确实可以工作,因为mock(1,2,3,4)
将正确地引发TypeError:太多的位置参数
,但这似乎是通过调用堆栈中更深的一些代码实现的。这不是通过电话签名来完成的
在实际依赖于签名本身的代码中(并且在测试中模拟时需要保留正确的签名),如何以正确保留签名的方式自动检测模拟?这实际上被认为是Python中的一个bug,并且一直被忽略。一个补丁也被删除了。相关问题和请求:
- :
\uuuu signature\uuu
属性设置为原始属性来解决这个问题:
from inspect import signature
from unittest.mock import patch
def foo(a, b, c):
pass
foo_sig = signature(foo) # Need to cache the signature before mocking foo
with patch("__main__.foo") as mock:
mock.__signature__ = foo_sig
print(signature(mock)) # Prints '(a, b, c)'
这是因为在尝试其他方法之前,signature()
函数遵循\uuuuuuuuuuuuuuuu签名
属性,如中所述:
如果对象具有\uuuu签名\uuuuu
属性,而不是None
,则返回它
不幸的是,
inspect
模块中没有提到这一点。是mock.assert\u调用了执行此检查的手动方式?(即,不是自动检测,而是检查签名)此问题现已在上游解决。如果您最近升级了Python3.7.3+,并且仍然手动设置\uuuuu签名\uuuuu
,我认为您可以从代码中删除它(直接编辑您的答案以在顶部提及)。