【问题标题】:Can a mock side_effect iterator be reset after it has been exhausted?模拟 side_effect 迭代器可以在用完后重置吗?
【发布时间】:2014-11-07 16:32:06
【问题描述】:

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() 没有解决副作用。

【问题讨论】:

  • 传递无限迭代器怎么样? mock = MagicMock(side_effect=itertools.cycle([1,2]));您无需拨打reset_mock
  • @falsetru: 但如果模拟使用不正确,那么下一次调用模拟将给出错误的值。
  • 您是否尝试过重新分配side_effect
  • 重新分配迭代器是我一直在寻找的,但我怀疑使用itertools.xyz 来实现副作用会很方便,谢谢。

标签: python unit-testing python-2.7 mocking


【解决方案1】:

正如 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)

【讨论】:

  • 谢谢,我什至没有想过要这样做。你打败了@user2357112。
【解决方案2】:

请注意,从 Python 3.6 开始,您可以使用以下命令重置模拟 side_effectreturn_value

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

来自the docs

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

【讨论】:

  • 对于我在问题中的简单示例,这不会重置副作用,以便可以再次使用它。它完全消除副作用。做我的榜样;打印 mock.side_effect;重置它;然后再次打印 mock.side_effect - 你会看到它消失了
  • 刚刚遇到@wwii 指出的内容。文档可以在这里做一些澄清。
  • 诚然,这并不能回答确切的问题,但提到有一个用于重置模拟的side_effect=True 选项仍然非常有用。就我而言,在我被失败的测试用例卡住了几个小时之后,这个答案让我畅通无阻。
猜你喜欢
  • 2011-03-17
  • 2018-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-08
  • 1970-01-01
相关资源
最近更新 更多