Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I correctly use mock call_args with Python's unittest.mock?

Consider the following files:

holy_hand_grenade.py

def count(one, two, five='three'):
    print('boom')

test_holy_hand_grenade.py

from unittest import mock
import holy_hand_grenade

def test_hand_grenade():
    mock_count = mock.patch("holy_hand_grenade.count", autospec=True)
    with mock_count as fake_count:
        fake_count(1, 2, five=5)

        # According to https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.call_args
        # this should work
        assert fake_count.call_args.kwargs['five'] == 5

According to the docs, call_args should be:

This is either None (if the mock hasn’t been called), or the arguments that the mock was last called with. This will be in the form of a tuple: the first member, which can also be accessed through the args property, is any ordered arguments the mock was called with (or an empty tuple) and the second member, which can also be accessed through the kwargs property, is any keyword arguments (or an empty dictionary).

(emphasis mine)

But this blows up in my face, with TypeError: tuple indices must be integers or slices, not str

Um. No?

The thing I really don't understand, is that if this is a call object, which it is, because

assert isinstance(fake_count.call_args, (mock._Call,))

passes, it's supposed to have kwargs and args. And it... well, it sort of does. But they appear to not actually be the correct thing:

assert isinstance(fake_count.call_args.kwargs, (mock._Call,))  #this works
assert isinstance(fake_count.call_args.kwargs, (dict,))  # doesn't work

What am I doing wrong here?

like image 617
Wayne Werner Avatar asked Feb 07 '20 00:02

Wayne Werner


People also ask

How do you mock a class in Unittest Python?

To mock objects, you use the unittest. mock module. The unittest. mock module provides the Mock class that allows you to mock other objects.


1 Answers

This is a feature introduced in Python 3.8 in this issue.

The 3.7 documentation does not mention it (while the newest docs do) - so you have to access the arguments by index in Python < 3.8.

like image 176
MrBean Bremen Avatar answered Sep 19 '22 18:09

MrBean Bremen