如何在FastAPI测试中替换生命周期内的对象为假实现?
解决FastAPI测试中替换lifespan管理的Service实例问题
核心思路
通过定义统一接口规范真实/假实现,结合app.state存储应用级Service实例,再用依赖注入让端点获取实例。测试时只需替换lifespan中的初始化逻辑,就能全局替换为假实现。
步骤1:定义Service接口与实现
先给真实和假实现统一接口,保证类型兼容:
from abc import ABC, abstractmethod # 定义基础接口 class ServiceInterface(ABC): @abstractmethod def get_value(self) -> int: pass # 真实实现 class Implementation(ServiceInterface): def get_value(self) -> int: # 真实业务逻辑(比如从内存数据计算) return 0 def cleanup(self): # 真实清理逻辑(比如释放资源) pass # 测试用假实现 class ImplementationFake(ServiceInterface): def get_value(self) -> int: return 42
步骤2:原应用的Lifespan与依赖注入配置
用app.state存储Service实例,通过依赖注入函数提供给端点:
from fastapi import FastAPI, Depends app = FastAPI() # 依赖注入函数:从应用状态获取Service实例 def get_service() -> ServiceInterface: return app.state.service # 原应用生命周期管理:初始化真实实现 @app.lifespan async def app_lifespan(app: FastAPI): app.state.service = Implementation() yield # 应用运行期间保持实例 app.state.service.cleanup() # 应用结束时执行清理 # 业务端点:通过依赖注入获取Service @app.get("/value") async def get_value(service: ServiceInterface = Depends(get_service)): # 内存对象同步调用,无需await return {"value": service.get_value()}
步骤3:测试时替换为假实现
重新定义测试用的lifespan,初始化假实现,再创建测试用的应用实例:
from fastapi.testclient import TestClient # 测试用生命周期:初始化假实现 async def test_app_lifespan(app: FastAPI): app.state.service = ImplementationFake() yield # 假实现无需清理的话,这里之后可以空着 # 创建测试专用应用,替换lifespan并复用原端点 test_app = FastAPI(lifespan=test_app_lifespan) test_app.include_router(app.router) # 初始化测试客户端 client = TestClient(test_app) # 测试用例 def test_get_value(): response = client.get("/value") assert response.status_code == 200 assert response.json()["value"] == 42
关键说明
app.state是FastAPI官方推荐的应用级状态存储,保证Service实例在应用生命周期内唯一且可访问- 依赖注入函数
get_service封装了实例获取逻辑,端点无需关心实例来源,便于替换 - 测试时通过替换
lifespan,从根源上把Service实例换成假实现,所有端点都会自动使用假实例,无需修改端点代码
内容的提问来源于stack exchange,提问作者user2138149
相关产品推荐
相关产品推荐

