如何使用side_effect断言被测函数的多次不同调用参数?
使用side_effect验证mock函数的多次调用参数
你可以通过自定义断言函数作为side_effect,让mock函数每次被调用时自动检查传入参数是否符合预期,具体有两种实现方式:
方式一:用计数器匹配调用顺序
定义带调用计数器的函数,根据计数器值对应不同调用的预期参数:
def check_persist_params(*args, **kwargs): # 初始化调用计数器 if not hasattr(check_persist_params, "call_count"): check_persist_params.call_count = 0 # 按调用顺序断言参数 if check_persist_params.call_count == 0: assert args == (1, 2, 3, 4), f"第一次调用参数错误:实际{args}" # 若需验证关键字参数,添加此行 # assert kwargs == {"param_key": "param_val"}, f"第一次调用关键字参数错误:实际{kwargs}" elif check_persist_params.call_count == 1: assert args == (5, 6, 7, 8), f"第二次调用参数错误:实际{args}" # 同理验证关键字参数 # assert kwargs == {"another_key": "another_val"}, f"第二次调用关键字参数错误:实际{kwargs}" check_persist_params.call_count += 1 # 返回与原函数一致的返回值,避免被测代码报错 return None # 绑定side_effect并执行测试 mock_database_persist = mocker.patch("admin.bootstrap.grouping.database_persist") mock_database_persist.side_effect = check_persist_params your_test_function()
方式二:用预期参数列表顺序匹配
提前按调用顺序定义好参数组合,每次调用取出对应项断言:
# 按调用顺序存储预期的(位置参数, 关键字参数) expected_calls = [ ((1, 2, 3, 4), {"param1": "val1"}), ((5, 6, 7, 8), {"param2": "val2"}) ] def check_persist_params(*args, **kwargs): expected_args, expected_kwargs = expected_calls.pop(0) assert args == expected_args, f"参数不匹配:预期{expected_args},实际{args}" assert kwargs == expected_kwargs, f"关键字参数不匹配:预期{expected_kwargs},实际{kwargs}" return None # 绑定side_effect并执行测试 mock_database_persist = mocker.patch("admin.bootstrap.grouping.database_persist") mock_database_persist.side_effect = check_persist_params your_test_function()
关键注意点
- 若原函数的
**params关键字参数需要验证,必须在断言中加入对kwargs的检查 - 自定义函数的返回值要和原
database_persist函数一致,避免被测代码因返回值异常中断 - 这种实时断言方式会在调用出错时立刻抛出异常,比事后检查
mock_database_persist.call_args_list更高效定位问题
内容的提问来源于stack exchange,提问作者Patrick Chong
相关产品推荐
相关产品推荐

