Python 3 mock objects支持查询其调用的参数,是否可以查询它们的调用返回的值?
我的特殊情况是我模拟tempfile.mkdtemp,但作为副作用调用真正的mkdtemp。我想在我的测试中掌握创建的临时目录。
from unittest import mock
import shutil
import tempfile
from app import production_function
def mkdtemp(*args, **kwargs):
dtemp = orig_mkdtemp(*args, **kwargs)
return dtemp
orig_mkdtemp = tempfile.mkdtemp
patcher = mock.patch('tempfile.mkdtemp', name='tempfile.mkdtemp')
the_mock = patcher.start()
the_mock.side_effect = mkdtemp
# Call function under test
production_function()
assert the_mock.called
# Now, how to get the return value from the call to the_mock?
patcher.stop()
答案 0 :(得分:1)
不幸的是mock
模块没有存储返回值(我看了一下debugguer并且没有任何跟踪)。您必须先存储它,然后才能返回side_effect
。
您可以使用对象来处理脏工作。例如,一个非常基础的实现可以是这样的:
class SideEffect():
def __init__(self, n):
self.values = iter(range(n))
self.return_value = None
def __call__(self):
self.return_value = next(self.values)
return self.return_value
a = Mock()
se = SideEffect(10)
a.side_effect = se
for x in range(10):
v = a()
assert v == se.return_value
print("a()={} return_value={}".format(v, se.return_value))
如果你想要一个更复杂的side_effect
来包装一个函数并处理参数和异常,可以是一个例子:
class GenericSideEffect():
def __init__(self, f, *args, **kwargs):
self.v_function = f
self.args = args
self.kwargs = kwargs
self._return_value = Exception("Never Called")
def __call__(self):
try:
self._return_value = self.v_function(*self.args, **self.kwargs)
return self._return_value
except Exception as e:
self.return_value = e
raise e
@property
def return_value(self):
if isinstance(self._return_value, Exception):
raise self._return_value
return self._return_value
当然你可以把它写成装饰器并保留签名,但我认为那部分超出了答案的范围。
答案 1 :(得分:0)
如果comportment是确定性的并且状态较少,则可以获得对mock进行的调用列表,并再次调用您感兴趣的嵌套调用来捕获结果。另外我想你可以做类似的事情:
def mkdtemp_wrapper(result_storage):
def mkdtemp(*args, **kwargs):
dtemp = orig_mkdtemp(*args, **kwargs)
result_storage.append(((*args,**kwargs),dtemp))
return dtemp
return mkdtemp
以这种方式修改模拟:
results_values = []
the_mocks.side_effect = mkdtemp_wrapper(result_values)
然后,您将在结果值中包含几个参数列表,结果。
希望它有所帮助。