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

时间:2017-09-15 13:44:25

标签: python unit-testing python-unittest

我有一个非常有用的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()

但如果close的返回值未评估为True,我想测试调用load_widget_from_file时该怎么办?

如果我尝试用另一个单元测试:

@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()
这会爆炸。

1 个答案:

答案 0 :(得分:1)

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

在Python中,一个对象总是“真实的”,除非它具有零长度,或者它具有__bool__ method that returns False

  

对象.__布尔__(个体)

     

被要求实施真值测试和内置操作bool();应该返回FalseTrue。如果未定义此方法,则调用__len__()(如果已定义),如果对象的结果非零,则认为该对象为true。如果某个类既未定义__len__()也未定义__bool__(),则其所有实例都被视为true。

向模拟对象添加__bool__方法的“正确方法”可能是use MagicMock,它带有许多预先定义的Python“魔术方法”。但您还必须将返回值更改为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()