如何在pytest中为read_all_rows实现条件化Mock返回值?
基于pytest-mocker的参数化Mock返回方案
你可以通过Python标准库的unittest.mock工具,配合pytest-mocker实现简洁的参数匹配式Mock返回,无需编写复杂的side_effect函数,每个匹配规则可单独一行配置。
原生方案(无需额外依赖)
1. 导入匹配工具
从标准库中导入用于参数匹配的核心组件:
from unittest.mock import call, ANY
其中ANY对应你需求中的any_string(),可匹配任意字符串类型的参数。
2. 配置Mock规则
先patch目标方法获取Mock实例,再通过字典定义参数组合与返回值的对应关系,字典键用call()封装参数:
# 将目标方法替换为Mock对象 mock_read = mocker.patch('db_access.read_all_rows') # 每行一个匹配规则,清晰直观 mock_read.side_effect = { call('table_name1', ANY): ['testRow1'], call('table_name2', 'mode1'): ['testRow2', 'tableRow3'], call('table_name2', 'mode2'): ['testRow2', 'tableRow3'], }
当read_all_rows被调用时,会自动匹配对应的参数组合返回预设值;若出现未匹配的参数调用,会抛出KeyError。如果需要默认返回值,可额外处理:
# 定义未匹配参数时的默认返回逻辑 def default_return(*args): return [] # 改写side_effect为带默认值的逻辑 mock_read.side_effect = lambda *args: mock_read.match_rules.get(call(*args), default_return(*args)) # 单独存放匹配规则,保持可读性 mock_read.match_rules = { call('table_name1', ANY): ['testRow1'], call('table_name2', 'mode1'): ['testRow2', 'tableRow3'], call('table_name2', 'mode2'): ['testRow2', 'tableRow3'], }
贴近Mockito风格的第三方库方案
如果希望完全复刻Mockito的链式语法,可引入pytest-mockito库(先通过pip install pytest-mockito安装),写法和你的伪代码几乎一致:
from mockito import when, any # 每行一个规则,完全贴合需求中的伪代码 when(db_access).read_all_rows('table_name1', any()).thenReturn(['testRow1']) when(db_access).read_all_rows('table_name2', 'mode1').thenReturn(['testRow2', 'tableRow3']) when(db_access).read_all_rows('table_name2', 'mode2').thenReturn(['testRow2', 'tableRow3'])
验证示例
调用方法时会自动匹配返回:
print(db_access.read_all_rows('table_name1', '任意模式')) # 输出 ['testRow1'] print(db_access.read_all_rows('table_name2', 'mode1')) # 输出 ['testRow2', 'tableRow3']
内容的提问来源于stack exchange,提问作者dimnnv
相关产品推荐
相关产品推荐

