试图模拟函数返回值,但使用Mock
会导致在传递无效参数时不会引发异常:
In [1]: from unittest.mock import MagicMock, Mock, create_autospec
In [2]: def f(a):
...: return 1
...:
...: mf = Mock('f', autospec=True, return_value=2)
...: mf(None)
Out[2]: 2
In [3]: mf() # Why no error here?
Out[3]: 2
当使用create_autospec执行此操作时,它确实抛出了一个异常:
In [4]: mf2 = create_autospec(f)
In [5]: mf2(None)
Out[5]: <MagicMock name='mock()' id='140657928683232'>
In [6]: mf2()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-6-377889015999> in <module>
----> 1 mf2()
<string> in f(*args, **kwargs)
/usr/local/lib/python3.8/unittest/mock.py in checksig(*args, **kwargs)
177 func, sig = result
178 def checksig(*args, **kwargs):
--> 179 sig.bind(*args, **kwargs)
180 _copy_func_details(func, checksig)
181
/usr/local/lib/python3.8/inspect.py in bind(self, *args, **kwargs)
3023 if the passed arguments can not be bound.
3024 """
-> 3025 return self._bind(args, kwargs)
3026
3027 def bind_partial(self, /, *args, **kwargs):
/usr/local/lib/python3.8/inspect.py in _bind(self, args, kwargs, partial)
2938 msg = 'missing a required argument: {arg!r}'
2939 msg = msg.format(arg=param.name)
-> 2940 raise TypeError(msg) from None
2941 else:
2942 # We have a positional argument to process
TypeError: missing a required argument: 'a'
In [7]:
首先,您希望创建通过spec=f
而不是spec='f'
的Mock
。否则,您将给出一个字符串作为规范,而不是函数f
。
其次,mock没有autospec
参数。如果您阅读了文档的所有autospec部分,您会注意到autospec
总是在使用patch
或patch.object
的上下文中提及。这两人的签名中都有autospec
。
这意味着mock创建中的autospec
被接受为mock接受的剩余kwargs
的一部分。这些用于在mock使用时在mock上配置其他属性。
因此,当您的mock只是使用一个普通的spec
时,您可以确认它接受了一个本不应该存在的属性的读取:
from unittest.mock import Mock
def f(a,b):
return 1
mf = Mock(spec=f, autospec=True, return_value=2)
print(mf)
print(mf(None))
print(mf())
print(mf.autospec)
输出:
<Mock spec='function' id='139874223464352'>
2
2
True
所以,如果你像下面这样写代码,autospec就起作用了:
from unittest.mock import patch
def f(a):
return 1
with patch("__main__.f", autospec=True, return_value=2) as mf:
print(mf)
print(mf(None))
print(mf())
输出:
<function f at 0x7ff5a60a94c0>
2
Traceback (most recent call last):
... line 21, in <module>
print(mf())
...
TypeError: missing a required argument: 'a'