如何在模拟中有条件地调用orignal方法?
在这个例子中,我只想假设bar=='x'
的返回值。否则我想调用原始方法。
def mocked_some_method(bar):
if bar=='x':
return 'fake'
return some_how_call_original_method(bar)
with mock.patch('mylib.foo.some_method', mocked_some_method):
do_some_stuff()
我知道这有点奇怪。如果我想在mylib.foo.some_method
方面伪造do_some_stuff()
,那么它应该是无条件的。对some_method
的所有(不是一些)调用都应该被嘲笑。
在我的情况下,它是一个集成测试,而不是一个微小的单元测试,mylib.foo.some_method
是一种经常被使用的调度程序。在一个案例中,我需要伪造结果。
答案 0 :(得分:21)
如果你只需要替换行为而不需要模拟调用断言函数,你可以使用new
参数;否则你可以使用可以调用的side_effect
。
我猜some_method
是一个对象方法(而不是staticmethod
)所以你需要一个引用它的对象来调用它。您的包装器应该声明对象的第一个参数,并且您的补丁使用autospec=True
来使用side_effect
大小写的正确签名。
最后的技巧是保存原始方法引用并使用它来进行调用。
orig = mylib.foo.some_method
def mocked_some_method(self, bar):
if bar=='x':
return 'fake'
return orig(self, bar)
#Just replace:
with mock.patch('mylib.foo.some_method', new=mocked_some_method):
do_some_stuff()
#Replace by mock
with mock.patch('mylib.foo.some_method', side_effect=mocked_some_method, autospec=True) as mock_some_method:
do_some_stuff()
assert mock_some_method.called
答案 1 :(得分:1)
这里是一个示例,该示例说明如何动态修补类方法并在需要时执行原始方法
class CheckMockMethod:
def get_value_x_10(self, value):
"""Method which is going to be patched"""
return value*10
def wrapper_func():
"""Function which is called from test"""
for i in [1, 2, 3]:
print(CheckMockMethod().get_value_x_10(i))
import mock
from contextlib import contextmanager
@contextmanager
def mock_patch_method_original(mock_path, original_method, results):
results = iter(results)
def side_effect(self, *args, **kwargs):
value = next(results)
if value == '__original__':
side_effect.self = self
return original_method(self, *args, **kwargs)
else:
return value
patcher = mock.patch(mock_path, autospec=True, side_effect=side_effect)
yield patcher.start()
patcher.stop()
__original__
的值 from somewhere import CheckMockMethod
from test_helpers import mock_patch_method_original
def test_wrapper(self):
path = '<import-path>.CheckMockMethod.get_value_x_10'
orig = CheckMockMethod.get_value_x_10
results = [1000, '__original__', 3000]
with mock_patch_method_original(path, original_method=orig, results=results):
wrapper_func()
结果
通过模拟,您将看到
1000、20、3000
其中 1000 和 3000 是修补值,而 20 是原始值
答案 2 :(得分:1)
使用 return_value 或 side_effects 返回 unittest.mock.DEFAULT
将调用原始方法。这应该可以避免一些包装器。