根本问题是mock.call
返回 的实例mock._Call
,它本身就是 的子类tuple
。作为一个元组,它继承了元组的__iter__
方法,并且您将获得该实际方法,而不是像往常一样动态捕获属性访问以产生链式调用。
('__iter__', (), {})
一种可能比在呼叫列表中硬编码更好的解决方法是这样做call.__getattr__('__iter__')()
,其效果大致相同:
>>> mock.call.__getattr__('__iter__')() == ('__iter__', (), {})
True
(请注意,您不能这样做getattr(mock.call, '__iter__')
,因为那只会tuple.__iter__
再次为您提供实际方法)
或者,您可以子类mock._Call
化并构建自己的行为更好(至少相对于__iter__
)版本call
:
class _IterCall(mock._Call):
def __getattr__(self, attr):
if self._mock_name is None:
return type(self)(name=attr, from_kall=False)
name = '%s.%s' % (self._mock_name, attr)
return type(self)(name=name, parent=self, from_kall=False)
def __iter__(self):
return self.__getattr__('__iter__')()
iter_call = _IterCall(from_kall=True)
(它也必须重写__getattr__
,因为 的实现mock._Call.__getattr__
将显式返回原始mock._Call
类的实例而不是type(self)
)
>>> iter_call.__iter__() == ('__iter__', (), {})
True
这两种方法都有其缺点。