You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 18:18:28