FastAPI测试中无法覆写类类型依赖的问题
FastAPI依赖覆写失效:模块级变量未被替换的解决方案
你的问题根源在于模块加载时提前初始化了assistant变量,FastAPI的app.dependency_overrides仅对通过依赖注入系统(Depends装饰器声明的依赖)管理的对象生效。模块级的assistant = AssistantProvider.get_assistant('multi')在应用启动时就已执行,绑定了真实的MultiAssistant,后续的依赖覆写无法改变这个已初始化的变量引用。
方案1:将assistant改为FastAPI依赖项
修改路由文件,把assistant的获取逻辑纳入FastAPI依赖系统,让框架管理它的实例化:
# messages.py(修改后) from fastapi import APIRouter, Depends from modules.assistant.assistant import AssistantProvider router = APIRouter(...) def get_assistant(): return AssistantProvider.get_assistant('multi') @router.post("/start") async def start(data: InitialMessageBody, assistant = Depends(get_assistant)): agent_conversation = await assistant.initial_message(data.user) return agent_conversation
测试时直接覆写这个get_assistant依赖:
# test_my_test.py(修改后) from main import app from fastapi.testclient import TestClient from routers.messages import get_assistant client = TestClient(app) class MockAssistant: @staticmethod async def initial_message(user: str): return "Whatever message" def mock_get_assistant(): return MockAssistant app.dependency_overrides[get_assistant] = mock_get_assistant def test_start(): response = client.post('/messages/start', json={"user": "foo"}) assert response.json() == "Whatever message"
方案2:直接打桩AssistantProvider.get_assistant方法
如果不想修改路由代码,可使用Python标准库的unittest.mock直接替换目标方法的返回值:
# test_my_test.py(使用mock.patch) from main import app from fastapi.testclient import TestClient from unittest.mock import patch from modules.assistant.assistant import AssistantProvider client = TestClient(app) class MockAssistant: @staticmethod async def initial_message(user: str): return "Whatever message" def test_start(): with patch.object(AssistantProvider, 'get_assistant') as mock_get: mock_get.return_value = MockAssistant response = client.post('/messages/start', json={"user": "foo"}) assert response.json() == "Whatever message"
上下文管理器patch.object能确保打桩在路由处理前生效,且测试结束后自动恢复原方法。
原方法无效的核心原因
你之前尝试覆写AssistantProvider类,但模块级assistant变量在应用启动时就已通过原类的方法获取了实例。覆写类本身不会改变已存在的变量引用,只有让FastAPI依赖系统管理对象获取,或直接打桩目标方法,才能替换真实实现。
内容的提问来源于stack exchange,提问作者Alejandro Villegas
相关产品推荐
相关产品推荐

