'How to get the arguments passed to various calls from call_args_list?
I'm trying to use call_args_list to get the arguments passed to a certain function when it is called multiple times. I'm using this:
call_args_list = mock.add_row.call_args_list
Then I get a list that looks like this: [call('A', []), call('B', []), call('C', ['err'])]
.
If I only want to check that the second call doesn't have an error in the second argument and the third does, I need to somehow access the items within the call. Does anyone know how can I peel these call objects to get the items inside?
Solution 1:[1]
import unittest
import mock
class TestCase(unittest.TestCase):
def test_my_func(self):
m = mock.MagicMock()
m.add_row('A', [])
m.add_row('B', [])
m.add_row('C', ['err'])
calls = m.add_row.call_args_list
_first_arg, second_arg = calls[1][0]
self.assertNotEqual(second_arg, ['err'])
_first_arg, second_arg = calls[2][0]
self.assertEqual(second_arg, ['err'])
if __name__ == '__main__':
unittest.main()
Solution 2:[2]
def test_call_args(self):
m = mock.Mock()
m.add_row('A', ['a', 'aa'])
m.add_row('B', ['b', 'bb', 'bbb'])
m.add_row('C', ['c', 'cc', 'ccc', 'err'])
# args is a tuple, the second call
args, kwargs = m.add_row.call_args_list[1]
# the second arg is a list
self.assertTrue('err' not in args[1])
# third call
args, kwargs = m.add_row.call_args_list[2]
self.assertTrue('err' in args[1])
Solution 3:[3]
It doesn't appear to be (well) documented, but mock
defines a subclass of tuple
named _Call
, instances of which are what you see in call_args_list
. The first element is the name of the function, the second is a tuple of positional arguments, and the third a dict of keyword arguments.
Solution 4:[4]
There are ways of digging into these _Call
objects, but only to some extent. What if, for example, a parameter in a called mocked method is itself a Mock
?
Consider this:
def test_create_and_show_main_window_should_make_main_window_vis(qtbot):
with mock.patch('PyQt5.QtWidgets.QApplication'):
with mock.patch.object(MainWindow.the(), 'show') as mock_show:
with mock.patch('sys.exit') as mock_exit:
main_window_class.create_and_show_main_window()
mock_show.assert_called_once()
mock_exit.assert_called_once()
call = mock_exit.call_args_list[0]
call_arg = call.args[0]
assert call_arg._extract_mock_name() == 'QApplication().exec()'
In the above I want to test the following lines in my app code:
app_instance = QtWidgets.QApplication(sys.argv)
MainWindow.the().show()
sys.exit(app_instance.exec())
... it turns out that, in the above, call_arg
is of type unittest.mock.MagicMock
and that repr(call_arg)
is "<MagicMock name='QApplication().exec()' id='139817836711216'>"
.
A MagicMock
has a name
attribute, but if you try to use it directly it will create a new MagicMock
automatically rather than returning it: MagicMock
s are slippery, powerful objects. Fortunately, as illustrated above, the method _extract_mock_name
has been provided to obtain it.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Gang |
Solution 3 | chepner |
Solution 4 |