根据mock guide:
自动指定将创建具有与要替换的对象相同的属性和方法的模拟对象,并且任何函数和方法(包括构造函数)具有与真实对象相同的调用签名。
但是那似乎并不正确。 Stdlib inspect
仍然在模拟中看到通用的inspect
签名:
*args, **kwargs
autospec执行work,因为>>> 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
会正确地提高mock(1,2,3,4)
,但似乎这是通过调用堆栈中更深的一些代码实现的。不能通过呼叫签名来完成。
在您实际上依赖签名本身的代码中(并且在测试中进行模拟时需要保留正确的签名),如何以一种可以正确保留签名的方式自动指定模拟?
我有一个类似的问题,正在测试一些代码来检查可笑对象的签名。我通过将模拟的TypeError: too many positional arguments
属性设置为原始属性来解决它:
__signature__
这是可行的,因为在尝试其他方法之前,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()
属性,如__signature__
中所述:
如果对象具有PEP 362属性,但如果不是
__signature__
,则将其返回
很遗憾,None
或the documentation for the signature()
function模块中未提及。