FastAPI测试端点时如何跳过认证装饰器?
解决方案
方法1:临时替换路由的端点函数
直接找到对应路由,把它的endpoint替换成被装饰前的原始函数(通过__wrapped__获取),测试完成后再恢复,避免影响其他测试用例:
from fastapi.testclient import TestClient from main import app client = TestClient(app) def test_foo_skip_auth(): # 遍历路由找到目标端点 target_route = None for route in app.routes: if route.path == "/foo" and "GET" in route.methods: target_route = route break if not target_route: raise ValueError("Route /foo not found") # 保存原始端点,测试后恢复 original_endpoint = target_route.endpoint target_route.endpoint = original_endpoint.__wrapped__ try: response = client.get("/foo") assert response.status_code == 200 assert response.json() == {"message": "Authenticated user"} finally: target_route.endpoint = original_endpoint
方法2:在测试环境下自动跳过认证
修改你的认证装饰器,让它在测试环境中直接返回原始函数,不用执行认证逻辑:
import os from functools import wraps class Authentication: @staticmethod def authenticate(func): @wraps(func) async def wrapper(request: Request, *args, **kwargs): # 判断是否为测试环境 if os.getenv("TESTING") == "True": return await func(request, *args, **kwargs) # 正常环境的认证逻辑(保留原有代码) # ... 你的认证校验代码 ... return await func(request, *args, **kwargs) return wrapper
测试前设置环境变量即可:
import os from fastapi.testclient import TestClient from main import app os.environ["TESTING"] = "True" client = TestClient(app) def test_foo(): response = client.get("/foo") assert response.status_code == 200
方法3:改用FastAPI依赖注入(推荐)
把认证逻辑从装饰器改成FastAPI的依赖项,这样测试时可以通过dependency_overrides轻松替换或跳过:
重构后的业务代码
from fastapi import Depends, Request # 把认证逻辑抽成依赖函数 async def authenticate(request: Request): # 你的认证校验逻辑 # ... @app.get("/foo") async def bar(request: Request, _=Depends(authenticate)): return {"message": "Authenticated user"}
测试代码
from fastapi.testclient import TestClient from main import app, authenticate client = TestClient(app) def test_foo(): # 替换依赖为无操作函数 app.dependency_overrides[authenticate] = lambda: None try: response = client.get("/foo") assert response.status_code == 200 finally: # 清理依赖替换,避免影响其他测试 del app.dependency_overrides[authenticate]
内容的提问来源于stack exchange,提问作者Ghasem
相关产品推荐
相关产品推荐

