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