FastAPI + Dependency Injector





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 DependsFastAPI com marcadores Providee o Providerinjetor 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 Dependsagora funciona com marcadores Providee Provider.



Exemplo



Crie um arquivo fastapi_di_example.pye 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:8000deve retornar:



{
    "result": "Ok"
}




Como testar?



Crie um arquivo próximo tests.pya 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



All Articles