如何模拟会修改调用方逻辑所需参数的函数
问题描述
我需要模拟一个会修改可变参数的函数,且该参数的修改对代码正确执行至关重要。参考代码如下:
import os from unittest.mock import patch def mutate_my_dict(mutable_dict): if os.path.exists("a.txt"): mutable_dict["new_key"] = "new_value" return True def function_under_test(): my_dict = {"key": "value"} if mutate_my_dict(my_dict): return my_dict["new_key"] return "No Key"
注意:我知道这个例子里可以直接mockos.path.exists,但这只是示例,我有意要模拟mutate_my_dict而非外部模块。我也阅读过unittest.mock相关文档,但似乎不适用于我的场景。
我当前的测试代码无法正常工作,因为mock后的函数没有修改传入的字典,导致断言失败:
def test_function_under_test(): with patch("__main__.mutate_my_dict") as mutate_my_dict_mock: mutate_my_dict_mock.return_value = True result = function_under_test() assert result == "new_value"
解决方案
要让mock函数修改传入的可变参数,你需要利用side_effect定义mock的自定义行为,而不是仅设置return_value。side_effect可以接收一个函数,该函数会在mock被调用时执行,你可以在其中修改传入的参数:
from unittest.mock import patch def test_function_under_test(): def mock_mutate_dict(mutable_dict): # 模拟原函数的行为:修改传入的字典 mutable_dict["new_key"] = "new_value" return True with patch("__main__.mutate_my_dict", side_effect=mock_mutate_dict) as mutate_my_dict_mock: result = function_under_test() assert result == "new_value"
或者更简洁地用lambda表达式实现:
def test_function_under_test(): with patch("__main__.mutate_my_dict") as mutate_my_dict_mock: # 用lambda定义side_effect,修改传入的字典并返回True mutate_my_dict_mock.side_effect = lambda d: d.update({"new_key": "new_value"}) or True result = function_under_test() assert result == "new_value"
原理说明:side_effect指定的函数会在mock被调用时执行,接收原函数的参数。这里我们在mock函数里直接修改传入的字典,然后返回True,完全模拟了原函数mutate_my_dict在文件存在时的行为,这样function_under_test就能正确获取到修改后的键值,断言通过。
内容的提问来源于stack exchange,提问作者Nimrod Shanny
相关产品推荐
相关产品推荐

