Hola,
he lanzado una nueva versión de Dependency Injector 4.4. Le permite utilizar Dependency Injector con FastAPI . En esta publicación te mostraré cómo funciona.
La tarea principal de la integración es hacerse amigo de la directiva
Depends
FastAPI con marcadores Provide
y el Provider
Inyector de dependencias.
No funcionó de fábrica antes de DI 4.4. FastAPI usa escritura y Pydantic para la validación de entrada y respuesta. Los marcadores del inyector de dependencia lo desconcertaron.
La solución llegó después de examinar las partes internas de FastAPI. Tuve que realizar varios cambios en el módulo de cableado del inyector de dependencia. La directiva
Depends
ahora funciona con marcadores Provide
y Provider
.
Ejemplo
Cree un archivo
fastapi_di_example.py
y coloque las siguientes líneas en él:
import sys
from fastapi import FastAPI, Depends
from dependency_injector import containers, providers
from dependency_injector.wiring import inject, Provide
class Service:
async def process(self) -> str:
return 'Ok'
class Container(containers.DeclarativeContainer):
service = providers.Factory(Service)
app = FastAPI()
@app.api_route('/')
@inject
async def index(service: Service = Depends(Provide[Container.service])):
result = await service.process()
return {'result': result}
container = Container()
container.wire(modules=[sys.modules[__name__]])
Para ejecutar el ejemplo, instale las dependencias:
pip install fastapi dependency-injector uvicorn
y ejecutar
uvicorn
:
uvicorn fastapi_di_example:app --reload
La terminal debería mostrar algo como:
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [11910] using watchgod
INFO: Started server process [11912]
INFO: Waiting for application startup.
INFO: Application startup complete.
pero
http://127.0.0.1:8000
debería regresar:
{
"result": "Ok"
}
¿Cómo probar?
Cree un archivo junto
tests.py
a él y coloque las siguientes líneas en él:
from unittest import mock
import pytest
from httpx import AsyncClient
from fastapi_di_example import app, container, Service
@pytest.fixture
def client(event_loop):
client = AsyncClient(app=app, base_url='http://test')
yield client
event_loop.run_until_complete(client.aclose())
@pytest.mark.asyncio
async def test_index(client):
service_mock = mock.AsyncMock(spec=Service)
service_mock.process.return_value = 'Foo'
with container.service.override(service_mock):
response = await client.get('/')
assert response.status_code == 200
assert response.json() == {'result': 'Foo'}
Para ejecutar las pruebas, instale las dependencias:
pip install pytest pytest-asyncio httpx
y ejecutar
pytest
:
pytest tests.py
La terminal debe mostrar:
======= test session starts =======
platform darwin -- Python 3.8.3, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: ...
plugins: asyncio-0.14.0
collected 1 item
tests.py . [100%]
======= 1 passed in 0.17s =======
¿Qué aporta la integración?
FastAPI es un marco de construcción de API genial. El mecanismo básico de inyección de dependencia está integrado en él.
Esta integración mejora la inyección de dependencia en FastAPI. Le permite usar proveedores, anulaciones, configuraciones y recursos del inyector de dependencia en él.
¿Que sigue?
- Echa un vistazo al Github del proyecto
- Consulta la documentación
- Vea un ejemplo de FastAPI con varios módulos