Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Autospec mock未正确保留签名?_Python_Unit Testing_Mocking_Inspect - Fatal编程技术网

Python Autospec 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

根据报告:

自动指定创建的模拟对象具有与其替换的对象相同的属性和方法,并且任何函数和方法(包括构造函数)具有与真实对象相同的调用签名。

但这似乎不是真的。Stdlib仍然在mock上看到一个通用的
*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,并且一直被忽略。一个补丁也被删除了。相关问题和请求:

我有一个类似的问题,测试一些代码,检查被嘲笑的可调用的签名。我通过将mock的
\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
,我认为您可以从代码中删除它(直接编辑您的答案以在顶部提及)。