我的理解是MagicMock是一个Mock的超集,它自动执行“魔法方法”,从而无缝地提供对列表、迭代等的支持……那么plain Mock存在的原因是什么?这难道不是一个可以被忽略的MagicMock的精简版吗?Mock类知道在MagicMock中不可用的任何技巧吗?
当前回答
使用Mock,你可以模拟魔术方法,但你必须定义它们。MagicMock拥有“大多数magic方法的默认实现”。
如果您不需要测试任何神奇的方法,Mock就足够了,并且不会给您的测试带来很多无关的东西。如果您需要测试很多魔术方法,MagicMock将为您节省一些时间。
其他回答
使用Mock,你可以模拟魔术方法,但你必须定义它们。MagicMock拥有“大多数magic方法的默认实现”。
如果您不需要测试任何神奇的方法,Mock就足够了,并且不会给您的测试带来很多无关的东西。如果您需要测试很多魔术方法,MagicMock将为您节省一些时间。
这是python的官方文档 说:
在大多数示例中,Mock和MagicMock类是可互换的。由于MagicMock是功能更强的类,因此在默认情况下使用它是明智的。
首先,MagicMock是Mock的一个子类。
class MagicMock(MagicMixin, Mock)
因此,MagicMock提供了Mock所提供的一切,甚至更多。不要把Mock看作是MagicMock的简化版本,而应该把MagicMock看作是Mock的扩展版本。这将解决您的问题,即为什么存在Mock以及Mock在MagicMock之上提供了什么。
其次,MagicMock提供了许多/大多数magic方法的默认实现,而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
这些可能不是很直观(至少对我来说不是很直观):
>>> 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呢?
回到您的问题是:您是否同意默认的magic方法实现?例如,mocked_object[1]是否可以不出错?您是否可以接受由于魔术方法实现已经存在而产生的任何意外后果?
如果这些问题的答案是肯定的,那么继续使用MagicMock。否则,请继续使用Mock。
plain Mock存在的原因是什么?
Mock的作者Michael ford在Pycon 2011(31:00)上提出了一个非常相似的问题:
Q: Why was MagicMock made a separate thing rather than just folding the ability into the default mock object? A: One reasonable answer is that the way MagicMock works is that it preconfigures all these protocol methods by creating new Mocks and setting them, so if every new mock created a bunch of new mocks and set those as protocol methods and then all of those protocol methods created a bunch more mocks and set them on their protocol methods, you've got infinite recursion... What if you want accessing your mock as a container object to be an error -- you don't want that to work? If every mock has automatically got every protocol method, then it becomes much more difficult to do that. And also, MagicMock does some of this preconfiguring for you, setting return values that might not be appropriate, so I thought it would be better to have this convenience one that has everything preconfigured and available for you, but you can also take a ordinary mock object and just configure the magic methods you want to exist... The simple answer is: just use MagicMock everywhere if that's the behavior you want.
我发现了另一个简单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计算的。
这将是有效的,如果你使用Mock:
self.assertDictEqual(my_dict, {
'hello': 'world',
'another': ANY
})
而如果你使用MagicMock,它将引发AssertionError
推荐文章
- 从pandas DataFrame中删除名称包含特定字符串的列
- Mock vs MagicMock
- 如何阅读一个。xlsx文件使用熊猫库在iPython?
- 如何访问熊猫组由数据帧按键
- Pandas和NumPy+SciPy在Python中的区别是什么?
- 将列表转换为集合会改变元素的顺序
- 如何在matplotlib更新一个情节
- TypeError: ` NoneType `对象在Python中不可迭代
- 如何在Vim注释掉一个Python代码块
- python标准库中的装饰符(特别是@deprecated)
- 如何从外部访问本地Django web服务器
- 删除字符串的最后3个字符
- 在python中执行no-op的标准方法是什么?
- 如何从生成器构建numpy数组?
- 什么时候我应该(不)想要在我的代码中使用熊猫apply() ?