FastAPI路由实例化时Mock字典失效的测试问题求助
问题根源
问题出在模块导入的时机:当你从main导入app时,main模块已经执行完毕——big_dictionary已加载,KeyName枚举也已经用原始字典生成完成。@patch是在测试函数运行时才替换main.big_dictionary,但此时枚举早已定型,根本不会使用新字典重新生成。
解决办法
方案1:重构代码,延迟应用初始化(推荐)
把枚举和FastAPI实例的创建封装成函数,这样可以在Mock生效后重新初始化应用,确保枚举使用Mock后的字典生成。
修改main.py:
from enum import Enum from fastapi import FastAPI from long_list import big_dictionary def create_app(): # 在函数内创建枚举,确保每次调用都用当前的big_dictionary生成 KeyName = Enum('KeyName', names=[key for key in big_dictionary]) app = FastAPI() @app.get("/") async def root(key_name: KeyName): return key_name return app # 保留原有的app导出,不影响正常运行 app = create_app()
对应的测试用例:
from fastapi.testclient import TestClient from unittest.mock import patch from main import create_app @patch('main.big_dictionary', {'test_entry3': 'value3', 'test_entry4': 'value4'}) def test_root(self): # 在Mock生效后创建app,此时枚举会用Mock的字典生成 app = create_app() client = TestClient(app) response = client.get('/', params={"key_name": "TEST_ENTRY3"}) self.assertEqual(response.status_code, 200) self.assertEqual(response.json(), "TEST_ENTRY3")
方案2:测试时重新加载模块
如果不想修改业务代码,可以在Mock生效后重新加载main模块,让它用新的字典重新生成枚举和应用。
测试用例代码:
from fastapi.testclient import TestClient from unittest.mock import patch import importlib import main def test_root(self): with patch('main.big_dictionary', {'test_entry3': 'value3', 'test_entry4': 'value4'}): # 重新加载main模块,触发模块内代码重新执行 importlib.reload(main) client = TestClient(main.app) response = client.get('/', params={"key_name": "TEST_ENTRY3"}) self.assertEqual(response.status_code, 200) self.assertEqual(response.json(), "TEST_ENTRY3")
方案3:直接修改枚举成员(临时hack)
如果既不想改业务代码,也不想重新加载模块,可以直接修改KeyName枚举的成员,测试后再恢复。
测试用例代码:
from fastapi.testclient import TestClient from unittest.mock import patch from main import app, KeyName def test_root(self): # 保存原始枚举成员,测试后恢复 original_members = KeyName.__members__.copy() # 添加Mock需要的枚举值 KeyName.__members__.update({ 'TEST_ENTRY3': KeyName('TEST_ENTRY3', 3), 'TEST_ENTRY4': KeyName('TEST_ENTRY4', 4) }) try: client = TestClient(app) response = client.get('/', params={"key_name": "TEST_ENTRY3"}) self.assertEqual(response.status_code, 200) self.assertEqual(response.json(), "TEST_ENTRY3") finally: # 恢复原始枚举结构 KeyName.__members__.clear() KeyName.__members__.update(original_members)
内容的提问来源于stack exchange,提问作者user10205830
相关产品推荐
相关产品推荐

