模拟side_effect迭代器可以在耗尽后重置吗?

时间:2014-09-13 18:12:30

标签: python unit-testing python-2.7 mocking

mock.reset_mock()不会重置副作用迭代器。有没有办法在不重新创建模拟的情况下执行此操作?

>>> from mock import MagicMock
>>> mock = MagicMock(side_effect = [1,2])
>>> mock(), mock()
(1, 2)
>>> mock()

Traceback (most recent call last):
  File "<pyshell#114>", line 1, in <module>
    mock()
  File "C:\Python27\Lib\site-packages\mock.py", line 955, in __call__
    return _mock_self._mock_call(*args, **kwargs)
  File "C:\Python27\Lib\site-packages\mock.py", line 1013, in _mock_call
    result = next(effect)
StopIteration
>>> mock.reset_mock()
>>> mock()

Traceback (most recent call last):
  ...
StopIteration
>>> mock = MagicMock(side_effect = [1,2])
>>> mock(), mock()
(1, 2)
>>> 

目的是在后续测试中重用模拟,但我怀疑,像生成器一样,它不能重新启动

所以(指向正确的方向后)(我迟到了)我查看了mock.py并发现side_effect是一个迭代器对象(不能重置一次耗尽):

def __set_side_effect(self, value):
    value = _try_iter(value)
    ...

def _try_iter(obj):
    ...
    try:
        return iter(obj)
    except TypeError:
        # XXXX backwards compatibility
        # but this will blow up on first call - so maybe we should fail early?
        return obj

def reset_mock()没有解决副作用。

2 个答案:

答案 0 :(得分:5)

正如user2357112所评论的那样,重新分配side_effect将解决您的问题。

>>> from mock import MagicMock
>>>
>>> lst = [1, 2]
>>> mock = MagicMock(side_effect=lst)
>>> mock(), mock()
(1, 2)
>>> mock.side_effect = lst  # <-------
>>> mock(), mock()
(1, 2)

答案 1 :(得分:-1)

请注意,自Python 3.6起,您可以使用以下命令重置模拟side_effectreturn_value

mock.reset_mock(return_value=True, side_effect=True)

来自the docs

如果要重置return_value或side_effect,则将相应的参数传递为True。子模拟和返回值模拟(如果有)也将重置。