Olá,
lancei uma nova versão do Dependency Injector 4.4. Ele permite que você use o Dependency Injector com FastAPI . Nesse post vou mostrar como funciona.
A principal tarefa da integração é fazer amizade com a diretiva
Depends
FastAPI com marcadores Provide
e o Provider
injetor de dependência.
Não funcionava fora da caixa antes do DI 4.4. FastAPI usa digitação e Pydantic para validação de entrada e resposta. Os marcadores do injetor de dependência o intrigaram.
A solução veio após examinar os internos do FastAPI. Tive de fazer várias alterações no módulo de fiação do injetor de dependência. A diretiva
Depends
agora funciona com marcadores Provide
e Provider
.
Exemplo
Crie um arquivo
fastapi_di_example.py
e coloque as seguintes linhas nele:
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 executar o exemplo, instale as dependências:
pip install fastapi dependency-injector uvicorn
e executar
uvicorn
:
uvicorn fastapi_di_example:app --reload
O terminal deve exibir 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.
mas
http://127.0.0.1:8000
deve retornar:
{
"result": "Ok"
}
Como testar?
Crie um arquivo próximo
tests.py
a ele e coloque as seguintes linhas nele:
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 executar os testes, instale as dependências:
pip install pytest pytest-asyncio httpx
e executar
pytest
:
pytest tests.py
O terminal deve exibir:
======= 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 =======
O que a integração oferece?
FastAPI é uma estrutura de construção de API legal. O mecanismo básico de injeção de dependência está embutido nele.
Essa integração melhora a experiência de injeção de dependência FastAPI. Ele permite que você use provedores, substituições, configuração e recursos do Injetor de Dependência nele.
Qual é o próximo?
- Confira o Github do projeto
- Confira a documentação
- Veja um exemplo de FastAPI com vários módulos