繁体   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