Mock vs MagicMock

时间:2013-06-19 01:49:02

标签: python mocking

我的理解是 MagicMock Mock 的超集,它自动执行“魔术方法”,从而无缝地提供对列表,迭代等的支持......然后是什么是 Mock 存在的原因?这不仅仅是 MagicMock 的精简版,几乎可以被忽略吗? Mock 类是否知道 MagicMock 中没有的任何技巧?

5 个答案:

答案 0 :(得分:87)

普通 Mock 存在的原因是什么?

Mock的作者Michael Foord致辞a very similar question at Pycon 2011 (31:00)

  

问:为什么MagicMock是一个单独的东西,而不仅仅是将该功能折叠到默认的模拟对象中?

     

答:一个合理的答案是,MagicMock的工作方式是通过创建新的模拟和预先配置所有这些协议方法   设置它们,所以如果每个新的模拟创建了一堆新的模拟和   将这些设置为协议方法,然后设置所有这些协议方法   创建了一堆更多的模拟并将它们设置在他们的协议方法上,   你有无限的递归...

     

如果您希望将模拟器作为容器对象访问,该怎么办?   错误 - 你不希望它工作?如果每个模拟都有自动   得到每种协议方法,然后变得更加困难   那。此外,MagicMock为您做了一些预先配置,   设置可能不合适的返回值,所以我想到了   拥有一切拥有一切的便利会更好   预先配置并可供您使用,但您也可以采取普通的   模拟对象,只需配置你想要存在的魔术方法......

     

简单的答案是:只要使用MagicMock就可以了   你想要的行为。

答案 1 :(得分:43)

使用Mock,可以模拟魔术方法,但你必须定义它们。 MagicMock有"default implementations of most of the magic methods."

如果您不需要测试任何魔术方法,Mock就足够了,并且不会给您的测试带来太多无关紧要的事情。如果你需要测试很多魔术方法,MagicMock会为你节省一些时间。

答案 2 :(得分:35)

首先,MagicMockMock的子类。

class MagicMock(MagicMixin, Mock)

因此,MagicMock提供了Mock提供的所有功能。而不是将Mock视为MagicMock的精简版本,将MagicMock视为Mock的扩展版本。这应该解决你关于为什么Mock存在以及Mock在MagicMock上提供什么的问题。

其次,MagicMock提供了许多/大多数魔术方法的默认实现,而Mock没有。有关所提供的魔术方法的更多信息,请参阅here

提供魔术方法的一些例子:

>>> 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

这些可能不那么直观(至少对我来说不直观):

>>> with MagicMock():
...     print 'hello world'
...
hello world
>>> MagicMock()[1]
<MagicMock name='mock.__getitem__()' id='4385349968'>

你可以&#34;看&#34;添加到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', ...]

那么,为什么不一直使用MagicMock?

回答你的问题是:你对默认的魔法方法实现没问题吗?例如,mocked_object[1]没有错误可以吗?由于神奇的方法实现已经存在,你是否可以承担任何意想不到的后果?

如果这些问题的答案是肯定的,那么请继续使用MagicMock。否则,坚持模拟。

答案 3 :(得分:9)

这就是python's official documentation 表示:

  

在大多数这些示例中,Mock和MagicMock类是可互换的。由于MagicMock是功能更强的类,因此默认情况下使用它是明智的。

答案 4 :(得分:0)

我发现了另一种特殊情况,其中简单 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

ANY进行比较可能很有用,例如,比较两个字典之间的几乎每个键,其中使用模拟来计算某些值。

如果您使用的是Mock,这将是有效的:


self.assertDictEqual(my_dict, {
  'hello': 'world',
  'another': ANY
})

如果您使用过AssertionError,它将引发MagicMock