模拟与MagicMock

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

简单模拟存在的原因是什么?

Mock的作者Michael Foord 在Pycon 2011( 31:00)上提到了一个非常类似的问题 :

问:为什么MagicMock做了一个单独的事情,而不是把这个能力折叠成默认的模拟对象?

答:一个合理的答案是,MagicMock的工作方式是通过创build新的Mock并设置它们来预configuration所有这些协议方法,所以如果每个新的模拟创build了一堆新的模拟,并将其设置为协议方法,然后将所有这些协议方法创build了一堆更多的嘲笑,并设置他们的协议方法,你有无限的recursion…

如果你想访问你的模拟作为一个容器对象是一个错误 – 你不希望这个工作? 如果每一个模拟都自动得到了每个协议的方法,那么这样做就变得困难得多了。 另外,MagicMock还为您进行了一些预configuration,设置了可能不太合适的返回值,所以我认为最好有一个预先configuration好的可用的便捷程序,但是您也可以采取普通的模拟对象,只是configuration你想要存在的魔术方法…

简单的答案是:只要使用MagicMock,如果这是你想要的行为。

有了模拟,你可以嘲笑魔法,但你必须定义它们。 MagicMock具有“大部分魔术方法的默认实现”。 。

如果你不需要testing任何魔术方法,那么Mock是足够的,不会给你的testing带来很多无关的东西。 如果你需要testing很多魔术方法,MagicMock会为你节省一些时间。

首先, MagicMockMock一个子类。

 class MagicMock(MagicMixin, Mock) 

因此,MagicMock提供了Mock提供的所有内容。 而不是把Mock看作是MagicMock的精简版本,可以把MagicMock看作是Mock的扩展版本。 这应该解决你为什么存在Mock的问题以及Mock在MagicMock上提供什么。

其次,MagicMock提供了许多/最神奇的方法的默认实现,而模拟不提供。 有关所提供的魔术方法的更多信息,请参阅此处 。

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

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

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

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

您可以“看到”添加到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。 否则,坚持模拟。

这是python的官方文档说:

在大多数这些例子中,Mock和MagicMock类是可以互换的。 由于MagicMock是更有能力的类,所以默认情况下使用它是明智的。