[英]Python3 mock replace function with another function
How do I mock a function with another function in python, that will also provide a mock object?如何使用 python 中的另一个函数来模拟一个函数,这也将提供一个模拟对象?
I have code that does something like:我有执行类似操作的代码:
def foo(arg1, arg2):
r = bar(arg1)
# does interesting things
I would like to substitute an implementation of the bar
function, have it return sane values, and make sure it's called with the right arguments.我想替换
bar
函数的实现,让它返回合理的值,并确保使用正确的参数调用它。
I've tried this, where fake_bar
is my simple replacement for bar
:我试过这个,其中
fake_bar
是我对bar
简单替代:
from unittest.mock import patch
def test_foo():
with patch("x.bar", fake_bar) as mock_bar:
actual = foo(arg1, arg2)
assert actual == expected
mock_bar.assert_called_once_with(arg1)
However, I get this error:但是,我收到此错误:
AttributeError: 'function' object has no attribute 'assert_called_once'
AttributeError: 'function' 对象没有属性 'assert_called_once'
I found this question which suggests using create_autospec.我发现这个问题建议使用 create_autospec。 However, mock.create_autospec does not preserve return values.
但是, mock.create_autospec 不保留返回值。
The python documentation suggests doing something like: python 文档建议执行以下操作:
mock_function = create_autospec(function, return_value='fishy')
However, my faked version of bar
has computed return values that are not static and not so simple to put into an inline lambda.但是,我伪造的
bar
版本计算出的返回值不是静态的,也不是那么容易放入内联 lambda 中。
I feel like I'm missing something obvious.我觉得我错过了一些明显的东西。 Is there a way to easily both mock a function and replace its implementation with something more complex than a static return value?
有没有一种方法可以轻松地模拟一个函数并用比静态返回值更复杂的东西替换它的实现?
Use the wraps
keyword argument:使用
wraps
关键字参数:
def test_foo():
with patch("x.bar", wraps=fake_bar) as mock_bar:
actual = foo(arg1, arg2)
assert actual == expected
mock_bar.assert_called_once_with(arg1)
Here, x.bar
is the fully qualified name of the function you are replacing, for example 'bigbusiness.account.AccountRepository.insert'.此处,
x.bar
是您要替换的函数的完全限定名称,例如“bigbusiness.account.AccountRepository.insert”。
mock_bar
will still be a Mock
(as is the default), but that Mock
will wrap the function fake_bar
, so the return value of mock_bar
is the return value of fake_bar
, rather than another Mock
instance. mock_bar
仍然将是一个Mock
(这是默认值),但Mock
将包装功能fake_bar
,这样的返回值mock_bar
是的返回值fake_bar
,而不是另一种Mock
实例。
AttributeError: 'function' object has no attribute 'assert_called_once
AttributeError: 'function' 对象没有属性 'assert_Called_once
Sounds like you are trying to path with a regular function.听起来您正在尝试使用常规函数进行路径处理。 Patch with a MagicMock object whose return value is the result of calling
fake_bar
.使用返回值是调用
fake_bar
的结果的 MagicMock 对象修补。
from unittest.mock import patch, MagicMock
def foo(arg1, arg2):
r = bar(arg1)
# does interesting things
def bar(arg):
return 2
def fake_bar():
#calculate 2!
return 2
def test_foo():
with patch("__main__.bar", MagicMock(return_value=fake_bar())) as mock_bar:
arg1,arg2 = 'a','b'
foo(arg1, arg2)
mock_bar.assert_called_once_with(arg1)
## mock_bar.assert_called_once_with('w')
print(mock_bar.call_args)
Variants:变体:
def test_foo():
with patch("__main__.bar", autospec=True) as mock_bar:
arg1,arg2 = 'a','b'
mock_bar.return_value = fake_bar()
foo(arg1, arg2)
mock_bar.assert_called_once_with(arg1)
print(mock_bar.call_args)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.