[英]FastAPI: How to test APIs by overriding functions in `Depends()`
[英]How to add depedency overriding in FastAPI testing
我是 FastAPI 的新手,我已經實現了所有內容,但是在測試 API 時我無法覆蓋依賴項。
這是我的代碼:
測試控制器.py
import pytest
from starlette.testclient import TestClient
from app.main import app
from app.core.manager_imp import ManagerImp
@pytest.fixture()
def client():
with TestClient(app) as test_client:
yield test_client
async def over_create_record():
return {"msg": "inserted successfully"}
app.dependency_overrides[ManagerImp.create_record] = over_create_record
def test_post(client):
data = {"name": "John", "email": "john@abc.com"}
response = client.post("/person/", json=data)
assert response.status_code == 200
assert response.json() == {"msg": "inserted successfully"}
controller.py
from app.controllers.v1.controller import Controller
from fastapi import status, HTTPException
from app.models.taxslip import Person
from app.core.manager_imp import ManagerImp
from app.core.duplicate_exception import DuplicateException
from fastapi_utils.cbv import cbv
from fastapi_utils.inferring_router import InferringRouter
router = InferringRouter(tags=["Person"])
@cbv(router)
class ControllerImp(Controller):
manager = ManagerImp()
@router.post("/person/")
async def create_record(self, person: Person):
"""
Person: A person object
returns response if the person was inserted into the database
"""
try:
response = await self.manager.create_record(person.dict())
return response
except DuplicateException as e:
return e
manager_imp.py
from fastapi import HTTPException, status
from app.database.database_imp import DatabaseImp
from app.core.manager import Manager
from app.core.duplicate_exception import DuplicateException
class ManagerImp(Manager):
database = DatabaseImp()
async def create_record(self, taxslip: dict):
try:
response = await self.database.add(taxslip)
return response
except DuplicateException:
raise HTTPException(409, "Duplicate data")
在測試中,我想覆蓋 ManagerImp class 中的 create_record function 以便我可以獲得此響應{"msg": "inserted successfully"}
。 基本上,我想模擬 ManagerImp create_record function。正如您在test_controller.py
中看到的那樣,我已經嘗試過,但我仍然得到原始響應。
您沒有使用依賴項注入系統來獲取ManagerImp.create_record
function,因此無需覆蓋任何內容。
由於您沒有使用 FastAPI 的Depends
來獲取依賴項 - FastAPI 無法返回替代項 function。
在您的情況下,您需要使用常規的 mocking 庫,例如 unittest.mock 或pytest-mock 。
我還想指出,默認情況下初始化共享依賴項將跨所有ControllerImp
實例共享同一個實例,而不是為每個ControllerImp
實例重新創建。
cbv 裝飾器稍微改變了一些東西,如文檔中所述:
對於每個共享依賴項,添加一個值為
Depends
類型的 class 屬性
因此,要使其與 FastAPI 的做事方式相匹配,並使cbv
裝飾器按照您的意願工作:
def get_manager():
return ManagerImp()
@cbv(router)
class ControllerImp(Controller):
manager = Depends(get_manager)
當你這樣做時,你可以按照你的計划使用dependency_overrides
:
app.dependency_overrides[get_manager] = lambda: return MyFakeManager()
如果您只想替換create_record
function,您仍然必須使用常規 mocking。
您還必須在測試完成后刪除依賴覆蓋,除非您希望它應用於所有測試,因此請在您的夾具中使用yield
,然后在夾具再次開始執行時刪除覆蓋。
我認為您應該將app.dependency_overrides
放在帶有@pytest.fixture
的 function 中。 嘗試將其放入您的client()
中。
@pytest.fixture()
def client():
app.dependency_overrides[ManagerImp.create_record] = over_create_record
with TestClient(app) as test_client:
yield test_client
因為每個測試都會運行新的app
,這意味着它將重置從一個測試到另一個測試的所有內容,並且只有與pytest
綁定的相關內容才會影響測試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.