我如何正确使用 mock call_args 和 Python 的 unittest.mock?

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

考虑以下文件:

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

根据文档,call_args 应该是:

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).

(强调我的)

但这在我面前爆炸了,TypeError: tuple indices must be integers or slices, not str

嗯。没有?

我真的不明白的是,如果这是一个调用对象,它就是,因为

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

通过,它应该有 kwargs 和 args。而且它……好吧,它有点像。但它们似乎并不是正确的:

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

我做错了什么?

这是 Python 3.8 在 this issue 中引入的功能。

3.7 documentation does not mention it (while the newest docs 做) - 所以你必须在 Python < 3.8.

中按索引访问参数