为什么 mock.patch.multiple 的行为与 DEFAULT 不同?
Why does mock.patch.multiple behave different with DEFAULT?
如果 patch.multiple
用作 method/function 装饰器,则修补对象是否为 mock.DEFAULT
时其行为会有所不同。
示例:
from unittest import mock
class A: pass
@mock.patch.multiple('__main__', A=mock.DEFAULT)
def with_default(*args,**kwargs):
if 'A' not in kwargs:
print("with_default: A not passed")
@mock.patch.multiple('__main__', A=mock.Mock())
def with_other(*args, **kwargs):
if 'A' not in kwargs:
print("with_other: A not passed")
with_default() # nothing
with_other() # -> "with_other: A not passed"
我没有看到这种行为的原因吗?我看不出它在所有情况下都没有将新模拟传递给函数的原因。
docs 说(重点是我的):
Use DEFAULT
as the value if you want patch.multiple()
to create mocks
for you. In this case the created mocks are passed into a decorated
function by keyword, and a dictionary is returned when
patch.multiple() is used as a context manager.
因此,当您不使用 DEFAULT
关键字时,您设置的修补方法 不会 传递给装饰函数。
您的 with_other
的装饰器案例可以重写为:
@mock.patch('__main__.A', new=mock.Mock())
def with_other():
... bla bla
即使您使用 new
属性,参数也不会传递给修饰函数,因为它假设您已经知道它并且您不需要将它作为参数获取。
一般来说:patch.multiple
可以用一堆简单的 patch
代替,其中路径由参数名称扩展并使用 new
设置值:
@patch.mutilple('foo', bar='bar', baz='baz')
成为
@patch('foo.baz', new='baz')
@patch('foo.bar', new='bar')
或通过 new
位置参数更简单:
@patch('foo.baz', 'baz')
@patch('foo.bar', 'bar')
如果 patch.multiple
用作 method/function 装饰器,则修补对象是否为 mock.DEFAULT
时其行为会有所不同。
示例:
from unittest import mock
class A: pass
@mock.patch.multiple('__main__', A=mock.DEFAULT)
def with_default(*args,**kwargs):
if 'A' not in kwargs:
print("with_default: A not passed")
@mock.patch.multiple('__main__', A=mock.Mock())
def with_other(*args, **kwargs):
if 'A' not in kwargs:
print("with_other: A not passed")
with_default() # nothing
with_other() # -> "with_other: A not passed"
我没有看到这种行为的原因吗?我看不出它在所有情况下都没有将新模拟传递给函数的原因。
docs 说(重点是我的):
Use
DEFAULT
as the value if you wantpatch.multiple()
to create mocks for you. In this case the created mocks are passed into a decorated function by keyword, and a dictionary is returned when patch.multiple() is used as a context manager.
因此,当您不使用 DEFAULT
关键字时,您设置的修补方法 不会 传递给装饰函数。
您的 with_other
的装饰器案例可以重写为:
@mock.patch('__main__.A', new=mock.Mock())
def with_other():
... bla bla
即使您使用 new
属性,参数也不会传递给修饰函数,因为它假设您已经知道它并且您不需要将它作为参数获取。
一般来说:patch.multiple
可以用一堆简单的 patch
代替,其中路径由参数名称扩展并使用 new
设置值:
@patch.mutilple('foo', bar='bar', baz='baz')
成为
@patch('foo.baz', new='baz')
@patch('foo.bar', new='bar')
或通过 new
位置参数更简单:
@patch('foo.baz', 'baz')
@patch('foo.bar', 'bar')