gpt4 book ai didi

python - FastAPI - 模拟路径功能没有效果

转载 作者:行者123 更新时间:2023-12-04 16:44:33 25 4
gpt4 key购买 nike

我有一个简单的 FastAPI应用程序,我正在尝试使用 pytest 创建测试为了它。

我的目标是测试应用程序在出现不同错误时的行为。

我的应用中有一个简单的健康检查路线:

from fastapi import APIRouter

router = APIRouter()


@router.get("/health")
async def health():
return "It's working ✨"

现在在我的 pytest 模块中,我试图修补上面的函数,以便它引发不同的错误。
我正在使用 unittest.mock但我的行为很奇怪。

import pytest
from unittest import mock

from fastapi import HTTPException
from starlette.testclient import TestClient

import app.api.health
from app.main import app # this is my application (FastAPI instance) with the `router` attached


@pytest.fixture()
def client():
with TestClient(app) as test_client:
yield test_client


def test_simple(client):
def mock_health_function():
raise HTTPException(status_code=400, detail='gibberish')

with mock.patch('app.api.health.health', mock_health_function):
response = client.get(HEALTHCHECK_PATH)

with pytest.raises(HTTPException): # this check passes successfully - my exception is raised
app.api.health.health()

assert response.status_code != 200 # this check does not pass. The original function was called as if nothing was patched

尽管在测试内部调用了完全相同的函数,但 API 测试客户端在我到达端点时仍然调用原始函数。

为什么 mock.patch在测试中未直接调用函数时无法正常工作?

或者我应该以不同的方式解决我的问题?

最佳答案

您可以使用 monkeypatch fixture 来修补您的功能。
先把要打补丁的代码部分拉出来:

from fastapi import FastAPI

app = FastAPI()


def response():
return "It's working ✨"


@app.get("/health")
async def health():
return response()
然后在你的测试中使用monkeypatch
import pytest

from fastapi import HTTPException
from starlette.testclient import TestClient

from app import main


def mocked_response():
raise HTTPException(status_code=400, detail='gibberish')


@pytest.fixture()
def client():
from app.main import app

with TestClient(app) as test_client:
yield test_client


def test_simple(client, monkeypatch):

monkeypatch.setattr(main, "response", mocked_response)
resp = client.get("/health")
assert resp.status_code == 400
assert resp.json()["detail"] == "gibberish"

另一种方法是使用 Dependencies , 连同 dependencies_overrides .
这可能不适用于所有场景,但对于您给定的用例来说确实如此。
from fastapi import FastAPI,  Depends

app = FastAPI()


def response():
return "It's working ✨"


@app.get("/health")
async def health(resp=Depends(response)):
return resp
在您的测试客户端中,您现在可以像这样覆盖依赖项:
import pytest

from fastapi import HTTPException
from starlette.testclient import TestClient

from app.main import response


def mocked_response():
raise HTTPException(status_code=400, detail='gibberish')


@pytest.fixture()
def client():
from app.main import app
app.dependency_overrides[response] = mocked_response

with TestClient(app) as test_client:
yield test_client


def test_simple(client):

resp = client.get("/health")

assert resp.status_code == 400
assert resp.json()["detail"] == "gibberish"

如果您需要向响应函数添加参数,您可以使用闭包模式
def response_closure():
def response(arg):
return arg
return response


@app.get("/health")
async def health(resp=Depends(response_closure)):
return resp("It's working ✨")

关于python - FastAPI - 模拟路径功能没有效果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60854208/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com