【问题标题】:How to mock a call to __next__如何模拟对 __next__ 的调用
【发布时间】:2015-08-17 13:07:23
【问题描述】:

我正在尝试模拟一个协程。因此,这个模拟的__next__()close() 被调用。虽然模拟 close() 有效,但我无法模拟 __next__()

    mock_coroutine = mock.Mock()
    mock_coroutine.some_call(1, 2, 3)
    mock_coroutine.some_call.assert_called_with(1, 2, 3)
    mock_coroutine.close()
    mock_coroutine.close.assert_called_with()
    #this fails
    mock_coroutine.__next__()
    mock_coroutine.__next__.assert_called_with()

我错过了什么?如何确保调用了我的 mock 的 __next__() 方法?

目前,我正在使用以下内容:

class MockCoroutine:
    def __next__(self):
        self.called_next = True

    def close(self):
        self.called_exit = True

但是,我更喜欢使用标准模拟。

【问题讨论】:

    标签: python unit-testing python-3.x mocking


    【解决方案1】:

    您需要使用MagicMock,而不是Mock,才能默认使用__next__ 等魔术方法:

    >>> from unittest import mock
    >>> mock_coroutine = mock.MagicMock()
    >>> mock_coroutine.__next__()
    <MagicMock name='mock.__next__()' id='4464126552'>
    >>> mock_coroutine.__next__.assert_called_with()
    

    引用the documentation:

    Mock 允许您将函数(或其他Mock 实例)分配给魔术方法,它们将被适当地调用。 MagicMock 类只是一个 Mock 变体,它为您预先创建了所有魔术方法(好吧,无论如何,所有有用的方法)。

    因此,或者,您仍然可以使用常规的 Mock 对象,但是您需要显式添加该属性:

    >>> mock_coroutine = mock.Mock()
    >>> mock_coroutine.__next__ = mock.Mock()
    >>> mock_coroutine.__next__()
    <Mock name='mock.__next__()' id='4464139232'>
    

    这是因为尽管Mock 在您访问它们时动态创建属性,但任何带有前导和尾随下划线的属性都被明确排除在外。见this footnote:

    唯一的例外是魔术方法和属性(具有前导和尾随双下划线的那些)。 Mock 不会创建这些,而是​​引发AttributeError。这是因为解释器经常会隐式地请求这些方法,并且当它需要一个魔术方法时,会非常困惑地获取一个新的 Mock 对象。如果您需要魔术方法支持,请参阅magic methods

    但请注意,魔术方法通常是在类上查找,而不是在实例上,因此直接将__next__ 属性添加到Mock 实例仍然会失败; MagicMock 类会为您解决这个特定问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-08
      • 2021-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-04
      相关资源
      最近更新 更多