This question is similar to check unittest.mock call arguments agnostically w.r.t. whether they have been passed as positional arguments or keyword arguments, but with an extension.
Given a mocked function with a given spec
, it is possible to check whether a function was called with the right arguments, regardless of whether the function was called with positional arguments or keyword arguments (or a mixture of both). So obviously, mock
knows how to translate between those two.
My problem is a little more complicated, because given this signature:
def myfun(a, b, some_list, c=3, d=4)
# Do something with a, b, c, d and some_list
return None
all the following calls should be regarded as correct:
myfun(b=2, a=1, some_list = [3, 4, 5])
myfun(1, 2, [5, 4, 3])
myfun(1, 2, d=4, some_list=[4, 3, 5])
The values for a
, b
, c
and d
should be 1
, 2
, 3
and 4
respectively, but the value for some_list
should just contain the values [3, 4, 5]
, without regard to order.
What I would like to do in a unittest is something like this (when complicated_fun
should at one point call myfun
with the given arguments):
def test_complicated_fun(self):
myobject = MyClass(...)
myobject.myfun = Mock(return_value = None, spec=myobject.myfun)
myobject.complicated_fun()
myobject.myfun.assert_called_once()
self.assertEqual(myobject.myfun.call_args['a'], 1)
self.assertEqual(myobject.myfun.call_args['b'], 2)
self.assertEqual(myobject.myfun.call_args['c'], 3)
self.assertEqual(myobject.myfun.call_args['d'], 4)
self.assertCountEqual(myobject.myfun.call_args['mylist'], [3, 4, 5])
Except this will of course fail, seeing as we can't subscript call_args
.
Is there a way around this, and to get the value of mylist
directly from the mock?
I could make a workaround it by using myobject.myfun.call_args[1].get('mylist', myobject.myfun.call_args[0][2])
.
But that:
- Depends on manually specifying again that
mylist
is the argument at index 2, meaning if my spec changes I should also manually edit the test. - Doesn't feel very pythonic