[英]FastAPI: How to test APIs by overriding functions in `Depends()`
我對 FastAPI 測試非常非常陌生,因此我們將不勝感激任何正確方向的指導。
所以我現在擁有的如下:
一個非常簡單的路由文件:datapoint_routes.py
from fastapi import APIRouter, Depends
datapoint_router = APIRouter()
def some_function_is():
return "Actual"
@datapoint_router.get('/{datapoint_name}')
def get_db(
datapoint_name: str,
some_function_output=Depends(some_function_is)
) -> dict:
return {
'datapoint_name': datapoint_name,
'state': some_function_output
}
我希望能夠對此進行測試。 我在這里查看了 FastAPI 測試依賴項指南。 但這根本沒有幫助,因為它對我不起作用。
對於我的測試,我現在擁有的是這樣的:
文件:test_datapoint_router.py
from typing import Union
from fastapi import FastAPI
from fastapi.testclient import TestClient
from datapoint_routes import datapoint_router, some_function_is
DATAPOINT_NAME = 'abcdef'
app = FastAPI()
client = TestClient(datapoint_router)
def override_dep(q: Union[str, None] = None):
return "Test"
app.dependency_overrides[some_function_is] = override_dep
def test_read_main():
response = client.get(f"/{DATAPOINT_NAME}")
assert response.status_code == 200
assert response.json() == {
'datapoint_name': DATAPOINT_NAME,
'state': "Test"
}
我希望在測試中, response = client.get()
將基於覆蓋函數override_dep
,它將替換some_function_is
。
我認為response.json()
將是:
{
'datapoint_name': 'abcdef',
'state': 'Test'
}
相反,它是:
{
'datapoint_name': 'abcdef',
'state': 'Actual'
}
這意味着測試中的override_dep
函數是沒有用的。
我什至檢查了app.dependency_overrides
的值,它顯示了正確的映射:
(Pdb) app.dependency_overrides
{<function some_function_is at 0x102b3d1b0>: <function override_dep at 0x102b3e0e0>}
函數的內存值匹配的地方:
(Pdb) some_function_is
<function some_function_is at 0x102b3d1b0>
(Pdb) override_dep
<function override_dep at 0x102b3e0e0>
我究竟做錯了什么?
您正在test 中創建 FastAPI app
對象,但您正在使用已定義的路由器與您的TestClient
。 由於此路由器從未在應用程序中注冊,因此使用應用程序覆蓋依賴項不會做任何有用的事情。
TestClient 通常與根應用程序一起使用(以便測試針對應用程序本身運行):
from fastapi import APIRouter, Depends, FastAPI
app = FastAPI()
datapoint_router = APIRouter()
def some_function_is():
return "Actual"
@datapoint_router.get('/{datapoint_name}')
def get_db(
datapoint_name: str,
some_function_output=Depends(some_function_is)
) -> dict:
return {
'datapoint_name': datapoint_name,
'state': some_function_output
}
app.include_router(datapoint_router)
然后是測試:
from typing import Union
from fastapi.testclient import TestClient
from datapoint_routes import app, datapoint_router, some_function_is
DATAPOINT_NAME = 'abcdef'
client = TestClient(app)
def override_dep(q: Union[str, None] = None):
return "Test"
app.dependency_overrides[some_function_is] = override_dep
def test_read_main():
response = client.get(f"/{DATAPOINT_NAME}")
assert response.status_code == 200
assert response.json() == {
'datapoint_name': DATAPOINT_NAME,
'state': "Test"
}
這按預期通過了,因為您現在正在針對應用程序( TestClient(app)
)進行測試 - 您覆蓋依賴項的位置。
MatsLindh 的回答確實解決了這個問題,我想提出另一項改進。
由於缺乏清理,覆蓋測試文件根目錄的依賴函數會引入干擾以下測試的風險。
相反,我建議使用夾具,這將確保您的測試隔離。 我編寫了一個簡單的 pytest 插件來與 FastAPI 的依賴系統集成以簡化語法。
通過以下方式安裝它: pip install pytest-fastapi-deps
然后像這樣使用它:
from typing import Union
from fastapi.testclient import TestClient
from datapoint_routes import app, datapoint_router, some_function_is
DATAPOINT_NAME = 'abcdef'
client = TestClient(app)
def override_dep(q: Union[str, None] = None):
return "Test"
def test_read_main_context_manager(fastapi_dep):
with fastapi_dep(app).override({some_function_is: override_dep}):
response = client.get(f"/{DATAPOINT_NAME}")
assert response.status_code == 200
assert response.json() == {
'datapoint_name': DATAPOINT_NAME,
'state': "Test"
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.