模拟函数默认使用装饰器



按照本答案中的方法,我能够使用以下方法覆盖函数的默认值,请参阅test_foo_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_foo_defaults2的事情,其中我只覆盖一个默认参数并获取它的句柄作为传递给我的测试函数的模拟。 不幸的是,test_foo_defaults2不起作用,但失败了:TypeError: getattr(): attribute name must be string.

对此有什么解决方案吗?

你试过吗:

@mock.patch.object(main.foo, '__defaults__', (5,))
def test_foo_defaults():
assert '3 5' == main.foo(3)

文档说unittest.mock.patch.object可以用作装饰器。

new_callable参数可用于替换初始化注入的模拟值的函数。

new_callable允许您指定将调用的不同类或可调用对象以创建新对象。默认情况下,AsyncMock用于异步函数,MagicMock用于其余功能。

来源: https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch

def init_mocked_defaults():
return (MagicMock(return_value=6), 5)

@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 5' == main.foo(3)

或者使用内联 lambda:

@mock.patch.object(
main.foo, "__defaults__",
new_callable=lambda: (MagicMock(return_value=6), 5)
)
def test_foo_defaults_2(defaults):
defaults[0].return_value = 12
assert '3 12 5' == main.foo(3)

说实话,这两种解决方案看起来都非常令人不安。

@Attila Viniczai,你的回答让我明白了一部分。另一个目的是避免必须在__defaults__中指定第二个元素。这对我有用:

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)

最新更新