如何使用Mock对Python嵌套for循环函数进行单元测试?两大疑问求助
单元测试解决方案
1. 如何Patch返回复杂类对象的fetch_rule_for函数
要模拟返回复杂的Rule对象,核心是用unittest.mock.Mock(或MagicMock)构造匹配原对象结构的模拟实例,步骤如下:
- 先构造模拟的
Action对象:设置name属性为目标值(比如'some_action_name') - 再构造模拟的
Rule对象:设置actions属性为包含上述Action的列表,同时设置attr1属性为测试用字符串 - 通过
side_effect让被patch的fetch_rule_for根据传入的id返回对应的Rule列表(支持不同id返回不同结果)
示例代码:
from unittest.mock import patch, Mock from main import my_func, Helper_class def test_my_func_complex_mock(): # 构造符合条件的Action对象 mock_target_action = Mock() mock_target_action.name = 'some_action_name' # 构造符合条件的Rule对象:包含目标action mock_valid_rule = Mock() mock_valid_rule.actions = [mock_target_action] mock_valid_rule.attr1 = 'test_attr_001' # 构造不符合条件的Rule对象:不包含目标action mock_invalid_rule = Mock() mock_invalid_rule.actions = [Mock(name='other_action')] mock_invalid_rule.attr1 = 'invalid_attr' # 定义mock函数的返回逻辑 def mock_fetch_logic(api, id): if id == 'id1': return [mock_valid_rule, mock_invalid_rule] elif id == 'id2': return [mock_invalid_rule] return [] with patch('main.fetch_rule_for', side_effect=mock_fetch_logic): # 执行测试函数 result = my_func(['id1', 'id2']) # 验证结果正确性 assert len(result['id1'].Attr1) == 1 assert mock_valid_rule in result['id1'].Attr1 assert result['id1'].Attr2 == {'test_attr_001'} assert len(result['id2'].Attr1) == 0 assert result['id2'].Attr2 == set()
2. 单元测试中处理for循环的方法
验证循环的执行次数与调用参数
call_count:直接获取被mock函数的调用次数,验证循环执行次数是否符合预期:from unittest.mock import patch, mock from main import my_func def test_loop_call_count(): with patch('main.fetch_rule_for') as mock_fetch: test_ids = ['id1', 'id2', 'id3'] my_func(test_ids) # 验证fetch_rule_for被调用了3次(对应3个id) assert mock_fetch.call_count == len(test_ids)call_args_list:查看每次调用的参数,验证循环中每个id都被正确传入:def test_loop_call_args(): with patch('main.fetch_rule_for') as mock_fetch: test_ids = ['id1', 'id2'] my_func(test_ids) # 验证每次调用的第二个参数是对应的id(第一个参数是api对象,用mock.ANY忽略具体值) expected_calls = [mock.call(mock.ANY, 'id1'), mock.call(mock.ANY, 'id2')] assert mock_fetch.call_args_list == expected_calls
验证循环内的业务逻辑
除了验证外部函数调用,还要验证循环内部的分支逻辑(比如符合条件的Rule是否被加入集合)。比如前面的测试示例中,通过断言result['id1'].Attr1包含有效mock_rule,就是验证嵌套循环里的if分支是否正确触发。
核心测试思路
for循环本质是对输入列表的每个元素执行逻辑,测试时只需覆盖三类场景:
- 空输入列表(循环完全不执行)
- 单个元素(单次循环,验证基础逻辑)
- 多个元素(多次循环,包含不同场景的元素,比如符合/不符合条件的id)
内容的提问来源于stack exchange,提问作者Lily Jinjia Li
相关产品推荐
相关产品推荐

