python - Autospec 模拟未正确保留签名?

标签 python unit-testing mocking inspect

根据mock guide :

Auto-speccing creates mock objects that have the same attributes and methods as the objects they are replacing, and any functions and methods (including constructors) have the same call signature as the real object.

但这似乎不是真的。标准库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 中的一个错误,并且已被 fixed in Python 3.8 。补丁也是backported to Python 3.7.3 。相关问题和拉取请求:

我遇到了类似的问题,测试了一些代码来检查被模拟的可调用对象的签名。我通过将模拟的 __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 中所述。 :

If the object has a __signature__ attribute and if it is not None - return it

不幸的是,the documentation for the signature() function 中没有提到这一点。或inspect 模块。

关于python - Autospec 模拟未正确保留签名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54099582/

相关文章:

python - 为什么 Keras Conv1D 权重在训练期间没有改变?

python - 使用 Numpy 进行傅立叶变换

python - 给定两个字符串列表,如何将它们转换为字典?

c# - 类方法输出字符串消息,由于错误引用从 void 到字符串的转换不适用,因此无法进行单元测试

python - Tastypie 如何将模型中的错误正确地反馈给用户?

unit-testing - EclEmma、powermock 和 Java 7 问题

java - 比较两个文件时如何忽略空格?

java - 如何模拟测试中的失败

python - 模拟父类(super class) __init__ 方法或父类(super class)作为一个整体进行测试

jestjs - 开 Jest ,我如何使用 "toHaveBeenCalledWith"并且只匹配数组参数中对象的一部分?