简体   繁体   中英

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

I've got a really useful python method like this:

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

when I want to test it to make sure I called close() , I do:

@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()

but what do I do when I want to test not calling close when the return value of load_widget_from_file doesn't evaluate to True?

If I tried making another unit test with:

@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()

this would blow up.

You need to create a second mock object (instead of setting mock_widget = None ), but the widget needs to be falsey to prevent the function from entering the if condition.

In Python, an object is always "truthy" unless is has a zero-length, or it has a __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.

Probably the "right way" to add a __bool__ method to your mock object would be to use MagicMock , which comes with many of the Python "magic methods" pre-defined. But you'll also have to change the return value to False , like so:

@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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM