Python 使用decorator模拟函数默认值
按照中的方法,我可以使用下面的方法覆盖函数的默认值,请参见Python 使用decorator模拟函数默认值,python,mocking,Python,Mocking,按照中的方法,我可以使用下面的方法覆盖函数的默认值,请参见test\u foo\u defaults main.py: def bar(x): return x * 2 def foo(a, b=bar, c=4): return f'{a} {b(a)} {c}' main_test.py import unittest from unittest import mock from unittest.mock import MagicMock import main de
test\u foo\u defaults
main.py:
def bar(x):
return x * 2
def foo(a, b=bar, c=4):
return f'{a} {b(a)} {c}'
main_test.py
import unittest
from unittest import mock
from unittest.mock import MagicMock
import main
def test_foo():
assert '3 6 4' == main.foo(3)
def test_foo_defaults():
m = MagicMock()
m.return_value = 12
with mock.patch.object(main.foo, '__defaults__', (m, 7)):
assert '3 12 7' == main.foo(3)
@mock.patch.object(main.foo.__defaults__, 0)
def test_foo_defaults_2(m):
m.return_value = 12
assert '3 12 5' == main.foo(3)
但是,我希望能够执行类似于test\u foo\u defaults2
的操作,其中我只覆盖一个默认参数,并将其句柄作为模拟传递给我的测试函数<很遗憾,代码>测试\u foo\u defaults2无法正常工作,但失败的原因是:类型错误:getattr():属性名称必须为字符串
有什么解决办法吗?您是否尝试过:
@mock.patch.object(main.foo, '__defaults__', (5,))
def test_foo_defaults():
assert '3 5' == main.foo(3)
文档中说,
unittest.mock.patch.object
可以用作装饰器。new\u callable
参数可以用来替换初始化注入的模拟值的函数
new_callable允许您指定将被调用以创建新对象的其他类或可调用对象。默认情况下,AsyncMock用于异步函数,MagicMock用于其余函数
资料来源:
def init_mock_defaults():
返回(MagicMock(返回值=6),5)
@object(main.foo,“\uuuuu默认值”\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu默认值),new\u callable=init\u mock\u
def测试_foo_默认值_2(默认值):
默认值[0]。返回值=12
断言'3125'==main.foo(3)
或使用内嵌lambda:
@mock.patch.object(
main.foo,“\uuuuu默认值”,
new_callable=lambda:(MagicMock(返回值=6),5)
)
def测试_foo_默认值_2(默认值):
默认值[0]。返回值=12
断言'3125'==main.foo(3)
老实说,这两种解决方案看起来都很令人不安。@Attila Viniczai你的回答让我了解了其中的一部分。另一个目的是避免在
\uuuuu defaults\uuuuu
中指定第二个元素。这对我很有用:
def init_mocked_defaults(**kwargs):
r = list(main.foo.__defaults__)
r[0] = MagicMock()
return tuple(r)
@mock.patch.object(main.foo, "__defaults__", new_callable=init_mocked_defaults)
def test_foo_defaults_2(defaults):
defaults[0].return_value = 12
assert '3 12 4' == main.foo(3)
很抱歉,我最初的问题不是很清楚,请看更新版本。