Python模拟补丁参数`new` vs`new_callable`

Jam*_*Lin 19 python mocking

来自文档http://www.voidspace.org.uk/python/mock/patch.html

patch(target, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs)
Run Code Online (Sandbox Code Playgroud)

如果省略new,则将目标替换为MagicMock.如果patch被用作装饰器而new被省略,则创建的mock将作为额外参数传递给装饰函数.如果将patch用作上下文管理器,则上下文管理器将返回创建的模拟.

new_callable允许您指定将被调用以创建新对象的不同类或可调用对象.默认使用MagicMock.

我试图了解两者之间的差异,以及使用什么情况new_callable而不是new

che*_*ner 28

new是一个实际的对象; new_callable是一个用于创建对象的可调用对象.这两个不能一起使用(您可以指定替换或创建替换的函数;使用两者都是错误.)

>>> foo = 6
>>> with mock.patch('__main__.foo', new=7):
...   print foo
...
7
>>> with mock.patch('__main__.foo', new_callable=lambda : 8):
...   print foo
...
8
Run Code Online (Sandbox Code Playgroud)

如果newmock.DEFAULT,模拟对象是一个MagicMock实例正是因为默认值new_callableMagicMock.


Mic*_*ico 6

[编辑] 在那个答案中,我错过了@chepner 正确说的最重要的事情,即new采用对象和new_callable可调用对象(工厂)。我不会删除它,因为它包含一些有用的注释。

通过挖掘代码https://code.google.com/p/mock/source/browse/mock.py#1266很明显,new您不能通过名义参数设置属性并使用specspec_set因为它会引发TypeError异常。

new_callable可以是NonCallableMock自身的子类,您可以在补丁定义中使用所有模拟工具。

当然,这种行为确实没有记录在案,而且在http://www.voidspace.org.uk/python/mock/changelog.html#version-0-8-0 中你找不到更多。

patch 和 patch.object 的新 new_callable 参数允许您传入一个类或可调用对象(而不是 MagicMock),它们将被调用以替换被修补的对象

无论如何,您不能使用类似的东西来创建YourMockSubclass具有myobject签名的

@patch("mymodule.myobject", new=YourMockSubclass(), spec=myobject)
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,您必须使用new_callable

@patch("mymodule.myobject", new_callable=YourMockSubclass, spec=myobject)
Run Code Online (Sandbox Code Playgroud)

所以new_callable每次你需要一个非 MagicMock 的模拟来做你的模拟时,你都必须使用。

恕我直言,唯一有用的用途是模拟属性。