Python不同版本unittest.mock call_args_list.kwargs类型差异及使用疑问
关于unittest.mock中call_args_list.kwargs类型跨版本差异的问题
在研究unittest.mock.patch的call_args_list特性时,发现跨Python版本存在类型差异:
- Python 3.7中,
call_args_list[0].kwargs的类型是<class 'unittest.mock._Call'> - Python 3.11中,该属性的类型是
<class 'dict'>
代码示例
from unittest import mock def foobar(foo = None, bar = None): print(f'args: {foo}, {bar}') l = None with mock.patch('__main__.foobar') as m: foobar(foo=1, bar=4) l = m.call_args_list type(l[0].kwargs)
问题解答
1. 该变更的相关说明在哪里?
这个变更属于unittest.mock内部实现的调整,并未在Python官方的What's New文档中单独提及,而是作为mock模块迭代优化的一部分。查看CPython的提交记录可以发现,Python 3.8到3.11的迭代过程中,开发团队重构了_Call类的属性暴露逻辑,将kwargs从_Call实例直接改为返回原生字典,目的是提升易用性,减少内部类型对外暴露。
2. 正确处理调用参数的方式是什么?
不管Python版本如何,推荐使用unittest.mock提供的标准化方法验证参数,避免直接依赖kwargs的类型:
解构调用参数:
call_args_list中的每个元素可以直接解构为位置参数和关键字参数,兼容所有版本:args, kwargs = m.call_args_list[0] assert kwargs.get('foo') == 'bar'使用mock断言方法:如果只需验证调用参数,直接用mock对象的断言方法更简洁直观:
# 验证最后一次调用的参数 m.assert_called_with(foo='bar', bar=4) # 验证是否存在符合条件的调用 m.assert_any_call(foo='bar')兼容旧版本的直接访问:如果必须直接操作
kwargs,可以通过dict()转换统一为字典类型:kwargs_dict = dict(l[0].kwargs) assert kwargs_dict['foo'] == 'bar'
内容的提问来源于stack exchange,提问作者eddie
相关产品推荐
相关产品推荐

