mock.MagicMock(spec=SomeClass)和mock.create\u autospec(SomeClass)之间有什么区别?

2024-05-23 19:50:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图理解这两种模拟结构之间的区别,以及何时使用这两种结构是合适的。我在解释器中进行了测试,例如:

>>> mm = mock.MagicMock(spec=list)
>>> ca = mock.create_autospec(list)
>>> mm
<MagicMock spec='list' id='140372375801232'>
>>> mm()
<MagicMock name='mock()' id='140372384057808'>
>>> mm.append()
<MagicMock name='mock.append()' id='140372375724720'>
>>> mm().append()
<MagicMock name='mock().append()' id='140372375753104'>
>>> ca
<MagicMock spec='list' id='140372384059248'>
>>> ca()
<NonCallableMagicMock name='mock()' spec='list' id='140372384057040'>
>>> ca.append()
<MagicMock name='mock.append()' id='140372375719744'>
>>> ca().append()
<MagicMock name='mock().append()' id='140372375796848'>
>>> 

但是我不明白为什么使用create_autospec创建的mock“构造”给了我一个NonCallableMagicMock,而MagicMock给了我更多的MagicMock。这个documentation帮不了什么忙


Tags: nameidcreate结构mock解释器listca
1条回答
网友
1楼 · 发布于 2024-05-23 19:50:26

使用spec参数和使用create_autospec之间的主要区别是递归性。在第一种情况下,对象本身是特定的,而被调用的对象不是:

>>> mm = mock.MagicMock(spec=list)
>>> mm
<MagicMock spec='list' id='2868486557120'>
>>> mm.foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:\Python\Python38\lib\unittest\mock.py", line 635, in __getattr__
    raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'foo'
>>> mm.append
<MagicMock name='mock.append' id='2868486430240'>
>>> mm.append.foo
<MagicMock name='mock.append.foo' id='2868486451408'>

在第二种情况下,调用的对象也被指定(延迟):

>>> ca = mock.create_autospec(list)
>>> ca
<MagicMock spec='list' id='2868486254848'>
>>> ca.foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:\Python\Python38\lib\unittest\mock.py", line 635, in __getattr__
    raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'foo'
>>> ca.append
<MagicMock name='mock.append' spec='method_descriptor' id='2868486256336'>
>>> ca.append.foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "c:\Python\Python38\lib\unittest\mock.py", line 635, in __getattr__
    raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'foo'

有一个警告,显示在示例代码中。如果如图所示使用create_autospec,它的行为就像对象是类而不是实例一样,因此您可以调用它(创建实例):

>>> ca = mock.create_autospec(list)
>>> ca()
<NonCallableMagicMock name='mock()' spec='list' id='2868485877280'>

如果您想让它像一个实例一样运行,您必须使用instance=True

>>> ca = mock.create_autospec(list, instance=True)
>>> ca
<NonCallableMagicMock spec='list' id='2868485875024'>
>>> ca()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NonCallableMagicMock' object is not callable

请注意,将mock.patchautospec=True一起使用会创建一个模仿,其行为类似于使用mock.create_autospec创建的模仿,如documentation中所述

还请注意,调用的返回值始终是MagicMock,而与实际调用的返回值无关。因此,即使函数返回None,如list.append,如果从模拟调用方法,则返回模拟,而不考虑规范

相关问题 更多 >