如何检查pytest中被patch的方法是否被调用及调用参数?
解决方法:通过patch获取mock实例来做调用断言与参数验证
你直接调用mpatch.assert_called_once()不行的原因是:patch对象本身不是mock实例,它只是用来管理mock替换的上下文工具。真正能做断言的是patch.start()返回的mock对象,或者用上下文管理器/装饰器方式拿到的mock实例。
下面给你几种可行的实现方式:
方式一:手动管理patch的启动与停止
适合需要更精细控制patch生命周期的场景:
from unittest.mock import patch # 创建patch对象 mpatch = patch('platform.blob_reader.BlobFilter.filter') # 启动patch,获取对应的mock实例 mock_filter = mpatch.start() try: # 执行会调用BlobFilter.filter的业务逻辑 # ...(比如调用相关的函数/方法) # 检查方法是否被调用过一次 mock_filter.assert_called_once() # 验证调用时传入的参数类型 # 获取最近一次调用的参数:args是位置参数元组,kwargs是关键字参数字典 args, kwargs = mock_filter.call_args # 示例:检查第一个位置参数是字符串类型 assert isinstance(args[0], str) # 示例:检查关键字参数data是列表类型 assert isinstance(kwargs.get('data'), list) finally: # 必须停止patch,恢复原方法的实现 mpatch.stop()
方式二:用上下文管理器(推荐)
不用手动start/stop,代码更简洁安全:
from unittest.mock import patch, ANY with patch('platform.blob_reader.BlobFilter.filter') as mock_filter: # 执行调用BlobFilter.filter的逻辑 # ... # 断言方法被调用一次 mock_filter.assert_called_once() # 验证参数类型:如果知道参数位置/名称,可结合ANY来匹配类型 # 示例:断言第一个参数是字符串,第二个关键字参数threshold是整数 mock_filter.assert_called_once_with(ANY(str), threshold=ANY(int)) # 如果需要更细致的类型检查,也可以直接取call_args来判断 args, kwargs = mock_filter.call_args assert isinstance(args[0], str) assert isinstance(kwargs['threshold'], int)
方式三:用装饰器
如果是在测试函数里,可以用装饰器自动管理patch:
from unittest.mock import patch, ANY @patch('platform.blob_reader.BlobFilter.filter') def test_filter_called(mock_filter): # 执行调用逻辑 # ... # 断言与参数验证 mock_filter.assert_called_once() args, kwargs = mock_filter.call_args assert isinstance(args[0], dict)
关键说明
- 所有的断言方法(
assert_called_once、assert_called_with等)和调用记录(call_args、call_args_list)都是mock实例的属性,不是patch对象的。 - 用patch的好处就是不需要修改原有代码的参数注入,直接替换目标方法为mock,完美适配嵌套较深的调用逻辑。
- 如果要检查多次调用的参数,可用
mock_filter.call_args_list获取所有调用的参数记录,循环逐个验证类型。
内容的提问来源于stack exchange,提问作者WestCoastProjects
相关产品推荐
相关产品推荐

