Python unittest使用mock.patch时如何动态调整db.find_one的返回值
问题根源
你之前的写法不生效的核心原因是:每次调用mocked_collection()(也就是模拟的get_share_code_collection()被调用)时,unittest.mock都会默认生成一个全新的MagicMock实例。你给临时生成的实例设置find_one.return_value,业务代码实际调用时拿到的是另一个新实例,之前的配置自然不会生效。
解决方案
方案1:固定返回同一个集合Mock实例(最常用)
提前创建一个Mock集合对象,让get_share_code_collection每次调用都返回同一个实例,后续直接修改这个实例的配置即可:
from unittest import mock @mock.patch("api.utils.get_share_code_collection") def test_share_code_correct_no_share_types( self, mocked_collection, mocked_share_code, user_model ): # 先创建固定的集合mock实例 mock_collection_inst = mock.MagicMock() mocked_collection.return_value = mock_collection_inst # 直接修改这个实例的find_one返回值即可 mock_collection_inst.find_one.return_value = True # 后续业务代码调用get_share_code_collection拿到的都是这个mock_collection_inst,配置生效 ... @mock.patch("api.utils.get_share_code_collection") def test_share_code_no_start_time( self, mocked_collection, user_model ): mock_collection_inst = mock.MagicMock() mocked_collection.return_value = mock_collection_inst # 单独设置当前测试用例需要的返回值 mock_collection_inst.find_one.return_value = False ...
方案2:动态追加side_effect返回值
如果同一个测试用例里需要多次调用find_one返回不同值,也可以动态修改side_effect列表,只要你持有同一个find_one的mock对象即可:
@mock.patch("api.utils.get_share_code_collection") def test_multiple_find_one_calls(self, mocked_collection): mock_collection_inst = mock.MagicMock() mocked_collection.return_value = mock_collection_inst # 初始化side_effect mock_collection_inst.find_one.side_effect = [True, False] # 后续可以直接追加新的返回值 mock_collection_inst.find_one.side_effect.append(None) mock_collection_inst.find_one.side_effect.extend([{"_id": 1}, {"_id": 2}]) ...
方案3:按查询条件返回对应值
如果需要根据find_one传入的查询参数动态返回不同结果,可以给side_effect传入自定义函数:
@mock.patch("api.utils.get_share_code_collection") def test_find_one_by_query(self, mocked_collection): mock_collection_inst = mock.MagicMock() mocked_collection.return_value = mock_collection_inst def custom_find_one(query): # 根据传入的查询条件返回对应值 if query.get("specialist_id") == {"$exists": True}: return {"specialist_id": 123, "code": "abc123"} elif query.get("code") == "test": return {"code": "test", "expired": True} return None mock_collection_inst.find_one.side_effect = custom_find_one ...
内容的提问来源于stack exchange,提问作者Vlaem
相关产品推荐
相关产品推荐

