如何在测试中引用FastAPI依赖,验证其下游传递正确性?
问题:验证FastAPI依赖的客户端是否正确传递给下游函数
现有FastAPI路由及依赖代码如下:
import httpx from fastapi import FastAPI, Depends, Request app = FastAPI() router = app.router async def get_client(): try: client = httpx.AsyncClient() yield client finally: await client.aclose() @router.get("/testendpoint") async def get( http_req: Request, client: httpx.AsyncClient = Depends(get_client), ): return await call_external_api(client) async def call_external_api(client: httpx.AsyncClient): return client.get("https://testapi/data")
编写测试时,无法直接引用依赖生成的客户端实例,验证它是否被正确传递给call_external_api:
from fastapi.testclient import TestClient import pytest_mock api_client = TestClient(app) def test_get(mocker: pytest_mock.MockFixture): mock_func = mocker.patch("call_external_api") response = api_client.get("/testendpoint") mock_func.assert_called_once_with(client) # client变量不存在,无法直接验证
解决方案
方法一:覆盖依赖,使用自定义可追踪的客户端实例
通过app.dependency_overrides替换原有的get_client依赖,返回预先创建的客户端实例,直接引用该实例做断言验证。
import httpx from fastapi.testclient import TestClient import pytest_mock from your_module import app, get_client api_client = TestClient(app) def test_get_with_dependency_override(mocker: pytest_mock.MockFixture): # 创建自定义的客户端实例 test_client = httpx.AsyncClient() # 覆盖依赖,让路由使用我们的实例 app.dependency_overrides[get_client] = lambda: test_client # patch目标函数 mock_func = mocker.patch("your_module.call_external_api") api_client.get("/testendpoint") # 验证调用时传入的是我们的自定义客户端 mock_func.assert_called_once_with(test_client) # 测试后清理依赖覆盖,避免影响其他测试 del app.dependency_overrides[get_client]
方法二:通过Mock的调用参数捕获验证
无需修改依赖,直接通过Mock对象的call_args属性获取实际传入的参数,验证其类型或特征。
from fastapi.testclient import TestClient import pytest_mock import httpx from your_module import app api_client = TestClient(app) def test_get_with_call_args_validation(mocker: pytest_mock.MockFixture): mock_func = mocker.patch("your_module.call_external_api") api_client.get("/testendpoint") # 获取调用时传入的第一个位置参数 called_client = mock_func.call_args[0][0] # 验证参数是httpx.AsyncClient实例 assert isinstance(called_client, httpx.AsyncClient) # 若需验证客户端配置,可添加更多断言(比如base_url等)
进阶:验证客户端的具体调用行为
如果需要进一步验证客户端是否按预期调用了外部API,可直接patch客户端的get方法:
from fastapi.testclient import TestClient import pytest_mock from your_module import app api_client = TestClient(app) def test_external_api_call(mocker: pytest_mock.MockFixture): # patch httpx.AsyncClient的get方法 mock_client_get = mocker.patch("httpx.AsyncClient.get") # 设置mock返回值 mock_client_get.return_value = {"status": "ok", "data": "test"} api_client.get("/testendpoint") # 验证客户端调用了正确的API地址 mock_client_get.assert_called_once_with("https://testapi/data")
内容的提问来源于stack exchange,提问作者anjuna47
相关产品推荐
相关产品推荐

