簡體   English   中英

如何在 FastAPI 測試中添加依賴覆蓋

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM