FastAPI 覆盖依赖和安全性

问题描述 投票:0回答:1

我在测试同时使用

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()
    ...
python dependency-injection pytest fastapi
1个回答
0
投票

app.dependency_overrides
通过使用 actual 函数实例作为键来工作 - 即传递给
Security
Depends
的确切函数实例。

如果这些函数不相同 - 要么因为它们注册到不同的实例,要么因为它们是动态生成的(例如通过返回另一个函数内定义的函数 - 通常作为闭包),则依赖关系将不会被覆盖(因为 FastAPI 无法知道用什么函数替换另一个函数)。

确保它们实际上是相同的实例和相同的函数。如果您在被调用的函数/方法内附加调试断点,您应该能够看到它们是否与您期望的相同(例如通过查看

self
或正在返回的函数)。

© www.soinside.com 2019 - 2024. All rights reserved.