代码:
from unittest.mock import Mock
mock = Mock()
print('mock.f():', id(mock.f()))
print('mock.f().g().h():', id(mock.f().g().h()))
print('mock():', id(mock()))
print('mock().f():', id(mock().f()))
print()
print('mock.f():', id(mock.f()))
print('mock.f().g().h():', id(mock.f().g().h()))
print('mock():', id(mock()))
print('mock().f():', id(mock().f()))
print()
print('mock.f(1):', id(mock.f(1)))
print('mock.f(2).g(3).h(4):', id(mock.f(2).g(3).h(4)))
print('mock(5):', id(mock(5)))
print('mock(6).f(7):', id(mock(6).f(7)))
print()
输出:
mock.f(): 4483288208
mock.f().g().h(): 4483354192
mock(): 4483368976
mock().f(): 4483708880
mock.f(): 4483288208
mock.f().g().h(): 4483354192
mock(): 4483368976
mock().f(): 4483708880
mock.f(1): 4483288208
mock.f(2).g(3).h(4): 4483354192
mock(5): 4483368976
mock(6).f(7): 4483708880
观察:
输出显示,在模拟上指定的链式函数调用总是在程序的生存期内返回相同的对象,不管我们调用了多少次。
例如,对mock.f().g().h()
的第一次调用,对mock.f().g().h()
的第二次调用,甚至第三次具有不同参数的mock.f(2).g(3).h(4)
调用都返回完全相同的对象。
问题:
mock.f().g().h()
会返回完全相同的模拟对象?mock.f(2).g(3).h(4)
)也会返回与mock.f().g().h()
相同的对象背景:
我问这个问题的原因是,与其编写这样的代码,不如:
from urllib import request
from unittest.mock import Mock, patch
with patch('urllib.request.urlopen') as mock_urlopen:
mock_urlopen.return_value = Mock()
mock_urlopen().getcode.return_value = 200
assert request.urlopen('').getcode() == 200
我可以编写这样的代码:
from urllib import request
from unittest.mock import Mock, patch
with patch('urllib.request.urlopen') as mock_urlopen:
mock_urlopen().getcode.return_value = 200
assert request.urlopen('').getcode() == 200
上面的例子太简单了,只是为了演示。我想保留一些完整的例子。但是如果我能够依赖这个特性,当函数调用链很长时,就会变得非常方便。这就是为什么我正在寻找某种类型的参考或文档,以表明我可以依赖于这种行为。
发布于 2019-08-24 13:14:02
如果您查看文件lib/python3.7/unittest/mock.py
def __getattr__(self, name):
if name in {'_mock_methods', '_mock_unsafe'}:
raise AttributeError(name)
elif self._mock_methods is not None:
if name not in self._mock_methods or name in _all_magics:
raise AttributeError("Mock object has no attribute %r" % name)
elif _is_magic(name):
raise AttributeError(name)
if not self._mock_unsafe:
if name.startswith(('assert', 'assret')):
raise AttributeError(name)
result = self._mock_children.get(name)
if result is _deleted:
raise AttributeError(name)
elif result is None:
wraps = None
if self._mock_wraps is not None:
# XXXX should we get the attribute without triggering code
# execution?
wraps = getattr(self._mock_wraps, name)
result = self._get_child_mock(
parent=self, name=name, wraps=wraps, _new_name=name,
_new_parent=self
)
self._mock_children[name] = result
elif isinstance(result, _SpecState):
result = create_autospec(
result.spec, result.spec_set, result.instance,
result.parent, result.name
)
self._mock_children[name] = result
return result
如您所见,对象被缓存在_mock_children
dict中。因此,每个调用都会返回对象。但数据将被更新。通过运行下面的代码,您可以看到
from unittest.mock import Mock
mock = Mock()
mock.a(10)
mock.a.assert_called_with(10)
mock.a(2)
mock.a.assert_called_with(10)
和结果
Traceback (most recent call last):
File ".../workbench.py", line 8, in <module>
mock.a.assert_called_with(10)
File ....lib/python3.7/unittest/mock.py", line 834, in assert_called_with
raise AssertionError(_error_message()) from cause
AssertionError: Expected call: a(10)
Actual call: a(2)
因此,是的,对象将是相同的,但是对象将具有更新的值。
https://stackoverflow.com/questions/57575929
复制相似问题