【发布时间】:2020-07-06 07:34:29
【问题描述】:
我有一个简单的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不能正常工作?
或者我应该以不同的方式解决我的问题?
【问题讨论】:
-
您必须修补由 sut 导入的模块 - 请参阅 where to patch 文档。您目前正在修补测试中导入的函数。
-
你能说明你是如何在你的测试代码中导入模拟函数的吗?
-
就像问题中一样:我导入整个模块
import app.api.health,然后直接调用函数app.api.health.health()。 (对不起那个嵌套)。health函数不会在其他任何地方导入,它只是在 FastAPI 路由器中注册 - 然后由框架调用。 -
嗯,在这种情况下,补丁实际上看起来是正确的......
-
似乎fastAPI的装饰器
@route.get(...)存储了对原始函数的引用。模拟修补函数,但它发生在路由已经注册并且修补对象具有不同的 id 引用之后。
标签: python pytest python-unittest fastapi starlette