我在测试同时使用
Depends
和 Security
的端点时遇到问题。首先,这是我的根端点,我可以使用 app.dependency_override
: 进行完美测试
# restapi/main.py
from api_v1.api import router as api_router
from authentication.verification import Verification
from fastapi import FastAPI, Security
from mangum import Mangum
app = FastAPI()
security = Verification()
@app.get("/")
async def root(auth_result: str = Security(security.verify)):
return {"message": "Hello World this is restapi.py!"}
app.include_router(api_router, prefix="/api/v1")
handler = Mangum(app)
然后测试一下:
from fastapi.testclient import TestClient
from restapi.main import app, security
def test_root_api():
client = TestClient(app=app)
app.dependency_overrides[security.verify] = lambda: ""
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"message": "Hello World this is restapi.py!"}
app.dependency_overrides = {}
def test_root_api_without_security():
client = TestClient(app=app)
response = client.get("/")
assert response.status_code == 403
assert response.json() == {"detail": "Not authenticated"}
仅使用
Security
功能时没有问题。但是我有另一个端点(我在 api_router 中定义为 api/v1/exchange_rates
),它同时具有 Depends
和 Security
:
# restapi/api_v1/endpoints/exchange_rates.py
security = Verification()
router = APIRouter()
@router.get("/")
async def exchange_rates(
query: ExchangeRatesQuery = Depends(),
auth_result: str = Security(security.verify),
):
ExchangeRatesQuery
是一个 pydantic BaseModel。仅当我从端点中删除 auth_result: str = Security...
时,以下针对此端点的测试才能完美运行。
from restapi.main import app
from restapi.api_v1.endpoints.exchange_rates import security
def test_exchange_rates():
client = TestClient(app=app)
app.dependency_overrides[security.verify] = lambda: ""
response = client.get(
"/api/v1/exchange-rates?start_date=2023-03-20&end_date=2023-03-21&base_currency=USD&target_currencies=EUR",
)
assert response.status_code == 200
assert response.json() == [
{
"exchange_date": "2023-03-20",
"exchange_rate": "0.88",
"base_currency": "USD",
"target_currency": "EUR",
}
]
app.dependency_overrides = {}
即使我从
security
导入 exchange_rates.py
以确保覆盖正确对象的依赖关系,但这似乎不起作用。非常感谢任何帮助。
编辑1 我还尝试使用 unittest.mock 使用标准返回值
""
修补验证函数,但也无法使其以这种方式工作。
@mock.patch.object(Verification, "verify", lambda: "") # also tried security instead of Verification
def test_exchange_rates()
...
app.dependency_overrides
通过使用 actual 函数实例作为键来工作 - 即传递给 Security
或 Depends
的确切函数实例。
如果这些函数不相同 - 要么因为它们注册到不同的实例,要么因为它们是动态生成的(例如通过返回另一个函数内定义的函数 - 通常作为闭包),则依赖关系将不会被覆盖(因为 FastAPI 无法知道用什么函数替换另一个函数)。
确保它们实际上是相同的实例和相同的函数。如果您在被调用的函数/方法内附加调试断点,您应该能够看到它们是否与您期望的相同(例如通过查看
self
或正在返回的函数)。