簡體   English   中英

MagicMock 的 reset_mock 未正確重置子模擬的 side_effect

[英]MagicMock's reset_mock not properly resetting sub-mock's side_effect

我在 class 上有一個長期存在的補丁,它的實例經歷了多批斷言。 請參閱下面的代碼片段以了解該場景。

它暴露了 MagicMock.reset_mock 中的(我認為很煩人的)行為,它似乎在子MagicMock.reset_mock MagicMock MagicMock

from unittest.mock import MagicMock

mock_cls = MagicMock()
mock_cls.return_value.method.side_effect = [5]
instance = mock_cls()

# Batch 1 of usage: uses side_effect
assert instance.method() == 5

mock_cls.reset_mock(return_value=True, side_effect=True)
# After this, mock_cls.return_value.method has a new id

# Batch 2 of usage: uses return_value
instance.return_value.method.return_value = 6
assert instance.method() == 6  # StopIteration

當使用 Python 3.10.2 運行時,它會引發StopIteration

Traceback (most recent call last):
  File "/path/to/code/play/quick_play.py", line 9, in <module>
    assert instance.method() == 6
  File "/path/to/.pyenv/versions/3.10.2/lib/python3.10/unittest/mock.py", line 1104, in __call__
    return self._mock_call(*args, **kwargs)
  File "/path/to/.pyenv/versions/3.10.2/lib/python3.10/unittest/mock.py", line 1108, in _mock_call
    return self._execute_mock_call(*args, **kwargs)
  File "/path/to/.pyenv/versions/3.10.2/lib/python3.10/unittest/mock.py", line 1165, in _execute_mock_call
    result = next(effect)
StopIteration

是否可以在不創建新MagicMock reset_mock

或者,如何手動重置side_effect以便片段運行?


在旁邊

reset_mock的簽名中的visited=None參數是什么? 它在3.10 文檔中沒有記錄,在這里

def reset_mock(self,  visited=None,*, return_value=False, side_effect=False):

有時在生活中,您會回答自己的問題。

替代reset_mock

來自side_effect 文檔

如果 function 返回DEFAULT則模擬將返回其正常值(來自return_value )。

from unittest.mock import MagicMock, DEFAULT

mock_cls = MagicMock()
mock_cls.return_value.method.side_effect = [5]
instance = mock_cls()
instance.method()

# Works, aligns with docs
mock_cls.return_value.method.side_effect = lambda: DEFAULT
instance.method()  # <MagicMock name='mock().method()' ...>

# Alternately, this works too
mock_cls.return_value.method.side_effect = None
instance.method()  # <MagicMock name='mock().method()' ...>

您還可以在此處找到使用的和在此處提及的


修復我的片段

這里有兩個學習:

  • 放棄reset_mock以支持設置side_effect = None
  • 第二批的return_value使用不正確
  • 或者,我可以在制作的instance上調用reset_mock
from unittest.mock import MagicMock

mock_cls = MagicMock()
mock_cls.return_value.method.side_effect = [5]
instance = mock_cls()

# Batch 1 of usage: uses side_effect
assert instance.method() == 5

mock_cls.return_value.method.side_effect = None
# instance.reset_mock(side_effect=True)  # Also works

# Batch 2 of usage: uses return_value
instance.method.return_value = 6  # Correct
# instance.return_value.method.return_value = 6  # Original incorrect
assert instance.method() == 6

未來的讀者:保持飢餓,保持愚蠢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM