我的理解是,MagicMock是Mock的超集,它自动执行"魔术方法",从而无缝地提供对列表,迭代等的支持......那么普通Mock存在的原因是什么?这不仅仅是MagicMock的精简版,几乎可以被忽略吗?Mock类是否知道MagicMock中没有的任何技巧?
Ryn*_*ett 91
Mock的作者Michael Foord 在Pycon 2011( 31:00)发表了一个非常类似的问题:
问:为什么MagicMock是一个单独的东西,而不仅仅是将功能折叠到默认的模拟对象中?
答:一个合理的答案是,MagicMock的工作方式是通过创建新Mocks并设置它们来预先配置所有这些协议方法,因此如果每个新模拟创建了一堆新模拟并将其设置为协议方法然后所有这些协议方法创建了一堆更多的模拟并在他们的协议方法上设置它们,你有无限的递归...
如果您希望将模拟作为容器对象访问是一个错误 - 您不希望它工作怎么办?如果每个模拟都自动获得每个协议方法,那么这样做会变得更加困难.而且,MagicMock会为你做一些预先配置,设置可能不合适的返回值,所以我认为最好有一个具有预配置和可用的一切的便利,但你也可以采取普通的模拟对象,只需配置你想要存在的魔术方法......
简单的答案是:如果这是您想要的行为,只需在任何地方使用MagicMock.
Sea*_*ond 49
使用Mock,您可以模拟魔术方法,但您必须定义它们.MagicMock拥有"大多数魔术方法的默认实现"..
如果您不需要测试任何魔术方法,Mock就足够了,并且不会给您的测试带来很多无关紧要的事情.如果你需要测试很多魔术方法,MagicMock会为你节省一些时间.
use*_*654 42
首先,MagicMock是一个子类Mock.
class MagicMock(MagicMixin, Mock)
Run Code Online (Sandbox Code Playgroud)
因此,MagicMock提供了Mock提供的所有功能.而不是将Mock视为MagicMock的精简版本,将MagicMock视为Mock的扩展版本.这应该解决你关于为什么Mock存在以及Mock在MagicMock之上提供什么的问题.
其次,MagicMock提供了许多/大多数魔术方法的默认实现,而Mock则没有.有关所提供的魔术方法的更多信息,请参见此处.
提供魔术方法的一些示例:
>>> int(Mock())
TypeError: int() argument must be a string or a number, not 'Mock'
>>> int(MagicMock())
1
>>> len(Mock())
TypeError: object of type 'Mock' has no len()
>>> len(MagicMock())
0
Run Code Online (Sandbox Code Playgroud)
这些可能不那么直观(至少对我来说不直观):
>>> with MagicMock():
... print 'hello world'
...
hello world
>>> MagicMock()[1]
<MagicMock name='mock.__getitem__()' id='4385349968'>
Run Code Online (Sandbox Code Playgroud)
您可以"看到"添加到MagicMock的方法,因为这些方法是第一次调用的:
>>> magic1 = MagicMock()
>>> dir(magic1)
['assert_any_call', 'assert_called_once_with', ...]
>>> int(magic1)
1
>>> dir(magic1)
['__int__', 'assert_any_call', 'assert_called_once_with', ...]
>>> len(magic1)
0
>>> dir(magic1)
['__int__', '__len__', 'assert_any_call', 'assert_called_once_with', ...]
Run Code Online (Sandbox Code Playgroud)
那么,为什么不一直使用MagicMock呢?
回答你的问题是:你对默认的魔术方法实现没问题吗?例如,mocked_object[1]没有错误可以吗?由于神奇的方法实现已经存在,你是否可以承担任何意想不到的后果?
如果这些问题的答案是肯定的,那么请继续使用MagicMock.否则,坚持模拟.
use*_*464 11
这是python的官方文档 所说的:
在大多数这些示例中,Mock和MagicMock类是可互换的.由于MagicMock是功能更强大的类,因此默认使用它是一个明智的选择.
我发现了另一个特殊情况,简单 Mock可能比以下更有用MagicMock:
In [1]: from unittest.mock import Mock, MagicMock, ANY
In [2]: mock = Mock()
In [3]: magic = MagicMock()
In [4]: mock.foo == ANY
Out[4]: True
In [5]: magic.foo == ANY
Out[5]: False
Run Code Online (Sandbox Code Playgroud)
比较ANY可能很有用,例如,比较两个字典之间的几乎每个键,其中某些值是使用模拟计算的。
如果您使用的是Mock:
self.assertDictEqual(my_dict, {
'hello': 'world',
'another': ANY
})
Run Code Online (Sandbox Code Playgroud)
AssertionError如果你使用过,它会引发MagicMock