如何在 Python unittest 库中模拟对对象方法的非调用

How to mock non-calls to object methods in Python unittest library

我有一个非常有用的 python 方法,如下所示:

def stop_widget():
  original_widget = load_widget_from_file()
  if original_widget: 
    original_widget.close()

当我想测试它以确保我调用了 close() 时,我会这样做:

@patch('load_widget_from_file')
def test_stop_widget_with_original_widget(self, lwff_mock):
    mock_widget = create_autospec(Widget)
    lwff_mock.return_value = mock_widget
    stop_widget()
    mock_widget.close.assert_called_once_with()

但是当我想测试 而不是 load_widget_from_file 的 return 值不计算时调用 close 我该怎么办为真?

如果我尝试使用以下方法进行另一个单元测试:

@patch('load_widget_from_file')
def test_stop_widget_with_original_widget(self, lwff_mock):
    mock_widget = None
    lwff_mock.return_value = mock_widget
    stop_widget()
    mock_widget.close.assert_not_called()

这会爆炸的。

您需要创建第二个模拟对象(而不是设置 mock_widget = None),但是小部件需要为 false 以防止函数进入 if 条件。

在 Python 中,一个对象总是 "truthy" 除非它的长度为零,或者它有一个 __bool__ method that returns False:

object.__bool__(self)

Called to implement truth value testing and the built-in operation bool(); should return False or True. When this method is not defined, __len__() is called, if it is defined, and the object is considered true if its result is nonzero. If a class defines neither __len__() nor __bool__(), all its instances are considered true.

可能 "right way" 将 __bool__ 方法添加到您的模拟对象 use MagicMock,它附带了许多 Python "magic methods"预定义。但您还必须将 return 值更改为 False,如下所示:

@patch('load_widget_from_file')
def test_stop_widget_with_original_widget(self, lwff_mock):
    mock_widget = MagicMock()
    mock_widget.__bool__.return_value = False
    lwff_mock.return_value = mock_widget
    stop_widget()
    mock_widget.close.assert_not_called()