如何在FastAPI应用程序的Pytest中正确实现模拟身份验证?

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

我正在使用 FastAPI 和 pytest 来测试我的应用程序中的端点。我需要模拟身份验证依赖项,但我在正确实现它方面面临挑战。我的主要目标是确保正确设置模拟身份验证,以便我的测试可以在不触及实际身份验证逻辑的情况下运行。

我的pytest代码

import os
from typing import Optional
from fastapi.testclient import TestClient
from unittest.mock import patch, AsyncMock
from main import app
from tests.mock_data import test_roles_data

os.environ["TEST_ENV"] = "test"
client = TestClient(app)

async def fake_authenticate(
        apitoken: Optional[str] = None,
        account: Optional[str] = None,
        sessionHost: Optional[str] = None
):
    return {
        'apitoken': 'apitoken',
        'account': 'account',
        'sessionHost': 'sessionHost',
    }

app.dependency_overrides[app.authenticate] = fake_authenticate

@patch('routers.base.parse_params', new_callable=AsyncMock)
@patch('services.roles.Roles.get_json', new_callable=AsyncMock)
def test_roles_endpoint(mock_parse_params, mock_get_json):
    mock_get_json.return_value = test_roles_data
    mock_parse_params.return_value = ("custom_fields_value", "2023-01-01", "2023-01-31")

    response = client.get("/roles", headers={
        'apitoken': 'apitoken',
        'account': 'account',
        'sessionHost': 'sessionHost',
    },
                          params={"start_date": "2023-01-01", "end_date": "2023-01-31"})

    assert response.status_code == 200
    # assert response.json() == test_roles_data


# Reset the environment variable after tests
del os.environ["TEST_ENV"]

但是,当我运行测试时,出现以下错误:

AttributeError: 'FastAPI' object has no attribute 'authenticate'

此错误发生在我尝试使用模拟身份验证函数覆盖依赖项的行。我确信

authenticate
函数存在于我的主应用程序中,并且在我的路线中正确使用。

我正在寻找有关如何在我的 FastAPI 应用程序的 pytest 设置中正确模拟身份验证的指导。实现此目的的正确方法是什么,以便我的端点测试可以绕过实际的身份验证逻辑?

附加信息

/main.py

async def authenticate(
    apitoken: Optional[str] = Header(""),
    account: Optional[str] = Header(""),
    sessionHost: Optional[str] = Header(""),
):

    print(sessionHost)
    if (
        sessionHost
        and sessionHost[-20:] == "mydomain-staging.com"
        or sessionHost == "https://apistaging.mydomain.com"
    ):
        url = sessionHost + "/api/jml/templates"
    else:
        url = PF_API_URL + "/jml/templates"

    print(url)

    params = {"per_page": 1, "page": 1}
    accept = "application/vnd.mydomain+json;version=2"
    auth_headers = {
        "content_type": "application/json",
        "accept": accept,
        "account": account,
        "apitoken": apitoken,
    }
    r = await session.get(url, headers=auth_headers, params=params, timeout=30)

    if r.status_code != 200:
        raise HTTPException(status_code=401, detail="Unauthorized")

    app.token_cache[apitoken] = {
        "account": account,
        "ts": datetime.now(),
    }


app.include_router(
    stats.router,
    dependencies=[Depends(authenticate)],
    responses={404: {"description": "Not found"}},
)

/路由器/stats.py

@router.get("/roles")
async def roles(
    request: Request,
    account: str = Header(...),
    start_date: str = None,
    end_date: str = None,
    profile_id: int = 0,
):

    custom_fields, start_date, end_date = parse_params(
        request, start_date, end_date
    )
    new_role = Roles(
        account, start_date, end_date, profile_id, custom_fields=custom_fields
    )

    try:
        await new_role.setup()
        result = await new_role.get_json()
    except NoDataException:
        result = {"Error": "No Data"}

    return result
python unit-testing mocking pytest fastapi
1个回答
0
投票

在您的测试模块中导入依赖项函数并使用它的名称来覆盖依赖项:

from main import app, authenticate

...

app.dependency_overrides[authenticate] = fake_authenticate
© www.soinside.com 2019 - 2024. All rights reserved.