Especialização em Backend com Python & FastAPI • Demonstrações Práticas Compiláveis


💻 Código de Exemplo 01 — Teste Síncrono de Endpoint com TestClient

# main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/health")
def health() -> dict:
    return {"status": "ok"}

@app.get("/itens/{item_id}")
def obter_item(item_id: int) -> dict:
    if item_id <= 0:
        return {"erro": "id inválido"}
    return {"id": item_id, "nome": f"Item {item_id}"}
# test_main.py
from fastapi.testclient import TestClient
from main import app

client = TestClient(app)

def test_health_ok():
    response = client.get("/health")
    assert response.status_code == 200
    assert response.json() == {"status": "ok"}

def test_obter_item_existente():
    response = client.get("/itens/10")
    assert response.status_code == 200
    assert response.json()["nome"] == "Item 10"

💻 Código de Exemplo 02 — Teste Assíncrono com httpx.AsyncClient e ASGITransport

# main_async.py
import asyncio
from fastapi import FastAPI

app = FastAPI()

@app.get("/processar")
async def processar_dados() -> dict:
    await asyncio.sleep(0.01)  # simula I/O assíncrono real (DB, HTTP externo)
    return {"itens": [1, 2, 3], "total": 3}
# test_main_async.py
import pytest
from httpx import AsyncClient, ASGITransport
from main_async import app

@pytest.mark.asyncio
async def test_processar_dados_assincrono():
    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://test") as client:
        response = await client.get("/processar")

    assert response.status_code == 200
    corpo = response.json()
    assert corpo["total"] == 3
    assert len(corpo["itens"]) == 3

💻 Código de Exemplo 03 — dependency_overrides com Banco SQLite em Memória

# app_pedidos.py
from fastapi import FastAPI, Depends
from sqlmodel import SQLModel, Field, Session, create_engine, select

class Pedido(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    cliente: str
    total: float

engine = create_engine("sqlite:///producao.db")  # banco real, nunca usado nos testes

def get_db():
    with Session(engine) as session:
        yield session

app = FastAPI()

@app.post("/pedidos", status_code=201)
def criar_pedido(cliente: str, total: float, db: Session = Depends(get_db)) -> Pedido:
    pedido = Pedido(cliente=cliente, total=total)
    db.add(pedido)
    db.commit()
    db.refresh(pedido)
    return pedido

@app.get("/pedidos")
def listar_pedidos(db: Session = Depends(get_db)) -> list[Pedido]:
    return db.exec(select(Pedido)).all()
# test_pedidos.py
import pytest
from fastapi.testclient import TestClient
from sqlmodel import SQLModel, create_engine, Session
from app_pedidos import app, get_db

engine_teste = create_engine("sqlite://", connect_args={"check_same_thread": False})

@pytest.fixture
def client():
    SQLModel.metadata.create_all(engine_teste)

    def get_db_teste():
        with Session(engine_teste) as session:
            yield session

    app.dependency_overrides[get_db] = get_db_teste
    with TestClient(app) as c:
        yield c

    app.dependency_overrides.clear()
    SQLModel.metadata.drop_all(engine_teste)

def test_criar_e_listar_pedido(client):
    resposta_criacao = client.post("/pedidos", params={"cliente": "Alice", "total": 250.0})
    assert resposta_criacao.status_code == 201

    resposta_listagem = client.get("/pedidos")
    assert resposta_listagem.status_code == 200
    assert len(resposta_listagem.json()) == 1
    assert resposta_listagem.json()[0]["cliente"] == "Alice"