Python单元测试中用patch为mock函数设置不同返回值的方法
在Python单元测试中为Mock函数设置不同返回值
要解决每次调用mock函数返回相同结果的问题,核心是利用unittest.mock.Mock的side_effect属性替代return_value,它支持按调用顺序返回不同结果,或根据传入参数动态返回对应数据,以下是两种常用实现方式:
方法一:按调用顺序返回固定列表值
如果测试中user_ids的顺序固定,直接给side_effect传入一个与调用次数匹配的返回值列表,每次调用mock函数时会依次取列表中的元素:
from unittest.mock import patch from your_module import get_users # 替换成你的主函数所在模块 import unittest class TestGetUsers(unittest.TestCase): @patch("api.get_users_from_api") def test_get_users(self, mock_get_users): user_ids = [1, 2, 3] # 按调用顺序设置对应返回值,分别匹配user_id 1、2、3 mock_get_users.side_effect = [ {"id": 1, "first_name": "John", "last_name": "Doe"}, {"id": 2, "first_name": "Jane", "last_name": "Smith"}, {"id": 3, "first_name": "Bob", "last_name": "Brown"} ] get_users(user_ids) # 可选:验证mock函数的调用情况 self.assertEqual(mock_get_users.call_count, 3) mock_get_users.assert_any_call(1) mock_get_users.assert_any_call(2) mock_get_users.assert_any_call(3)
方法二:根据传入参数动态返回值
如果需要根据调用时传入的user_id动态返回对应数据,可定义一个自定义函数,接收mock被调用时的参数,返回匹配的结果:
from unittest.mock import patch from your_module import get_users import unittest def mock_user_response(user_id): # 用字典映射user_id到对应的用户数据 user_data_map = { 1: {"id": 1, "first_name": "John", "last_name": "Doe"}, 2: {"id": 2, "first_name": "Jane", "last_name": "Smith"}, 3: {"id": 3, "first_name": "Bob", "last_name": "Brown"} } # 对于未定义的user_id,返回默认值 return user_data_map.get(user_id, {"id": user_id, "first_name": "Unknown", "last_name": "User"}) class TestGetUsers(unittest.TestCase): @patch("api.get_users_from_api") def test_get_users(self, mock_get_users): user_ids = [1, 3, 2, 4] # 将自定义函数赋值给side_effect mock_get_users.side_effect = mock_user_response get_users(user_ids) # 可选:验证特定调用的返回值 self.assertEqual(mock_get_users(4), {"id": 4, "first_name": "Unknown", "last_name": "User"})
补充说明
- 如果
side_effect传入的列表长度小于调用次数,超出次数的调用会抛出StopIteration异常; - 自定义函数的参数会与mock函数被调用时的参数完全一致,因此可以根据任意传入参数动态生成返回值;
- 若需要测试错误分支,也可以将异常类或实例传入
side_effect,触发异常场景。
内容的提问来源于stack exchange,提问作者user21656699
相关产品推荐
相关产品推荐

