Tests FastAPI

FastAPI basé sur StarletteTestClientFournit une prise en charge pratique des tests, vous permettant de tester les requêtes et réponses API sans démarrer un serveur.


Installer les dépendances

TestClientbasé surhttpx, vous devez installer :

pip install httpx

Test de base

UtilisationTestClientCréez un client de test, puis utilisez-le commehttpxenvoyez la requête de la même manière :

Exemple

from fastapi import FastAPI
from fastapi.testclient import TestClient

app = FastAPI()


@app.get("/")
async def root():
    return {"message": "Hello World"}


# Créer un client de test
client = TestClient(app)


# Fonction de test
def test_root():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"message": "Bonjour le monde"}

TestClientInvoque directement l'application FastAPI, en contournant la couche réseau, donc les tests s'exécutent très rapidement. Vous n'avez pas besoin de démarrer le serveur Uvicorn.


Tester différents types de requêtes

Exemple

from fastapi import FastAPI
from fastapi.testclient import TestClient
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str
    price: float


@app.post("/items/")
async def create_item(item: Item):
    return {"name": item.name, "price": item.price}


@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}


@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    return {"item_id": item_id, "name": item.name}


@app.delete("/items/{item_id}")
async def delete_item(item_id: int):
    return {"deleted": item_id}


client = TestClient(app)


# Tester la requête POST
def test_create_item():
    response = client.post(
        "/items/",
        json={"name": "Foo", "price": 42.0},  # Envoyer le corps de la requête JSON
    )
    assert response.status_code == 200
    assert response.json() == {"name": "Foo", "price": 42.0}


# Tester la requête GET
def test_read_item():
    response = client.get("/items/1")
    assert response.status_code == 200
    assert response.json() == {"item_id": 1}


# Tester la requête PUT
def test_update_item():
    response = client.put(
        "/items/1",
        json={"name": "Bar", "price": 50.0},
    )
    assert response.status_code == 200


# Tester la requête DELETE
def test_delete_item():
    response = client.delete("/items/1")
    assert response.status_code == 200
    assert response.json() == {"deleted": 1}

Tester les paramètres de requête et les en-têtes de requête

Exemple

from typing import Annotated
from fastapi import FastAPI, Header
from fastapi.testclient import TestClient

app = FastAPI()


@app.get("/items/")
async def read_items(
    skip: int = 0,
    limit: int = 10,
    x_token: Annotated[str | None, Header()] = None,
):
    return {"skip": skip, "limit": limit, "x_token": x_token}


client = TestClient(app)


# Tester les paramètres de requête
def test_read_items_with_params():
    response = client.get("/items/?skip=5&limit=20")
    assert response.status_code == 200
    assert response.json() == {"skip": 5, "limit": 20, "x_token": None}


# Tester les en-têtes de requête
def test_read_items_with_header():
    response = client.get(
        "/items/",
        headers={"X-Token": "fake-token"},  # Envoyer des en-têtes de requête personnalisés
    )
    assert response.status_code == 200
    assert response.json()["x_token"] == "fake-token"

Tester les réponses d'exception

Exemple

from fastapi import FastAPI, HTTPException
from fastapi.testclient import TestClient

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: int):
    if item_id == 0:
        raise HTTPException(status_code=404, detail="Item not found")
    return {"item_id": item_id}


client = TestClient(app)


# Tester une réponse normale
def test_read_item():
    response = client.get("/items/1")
    assert response.status_code == 200


# Tester la réponse d'erreur
def test_read_item_not_found():
    response = client.get("/items/0")
    assert response.status_code == 404
    assert response.json() == {"detail": "Élément introuvable"}


# Tester l'erreur de validation
def test_read_item_invalid_id():
    response = client.get("/items/foo")
    assert response.status_code == 422  # Échec de la validation

Exécutez les tests avec pytest

Enregistrez le code de test soustest_main.py, puis exécutez :

$ pytest test_main.py

# 显示详细输出
$ pytest test_main.py -v

# 显示 print 输出
$ pytest test_main.py -s

pytest découvrira automatiquement les fichiers et les fonctionstest_dont les noms commencent par le préfixe "test_".


Surcharger les dépendances dans les tests

Dans les tests, vous devrez peut-être surcharger certaines dépendances (telles que les connexions à la base de données, la logique d'authentification) :

Exemple

from fastapi import Depends, FastAPI
from fastapi.testclient import TestClient

app = FastAPI()


# Fonction de dépendance réelle
def get_query_param():
    return "real_value"


@app.get("/items/")
async def read_items(query: str = Depends(get_query_param)):
    return {"query": query}


client = TestClient(app)


def test_with_override():
    # Surcharger les dépendances
    app.dependency_overrides[get_query_param] = lambda: "test_value"

    response = client.get("/items/")
    assert response.json() == {"query": "test_value"}

    # Effacer les surcharges
    app.dependency_overrides.clear()

app.dependency_overridesPermet de remplacer n'importe quelle fonction de dépendance pendant les tests, ce qui est idéal pour simuler des scénarios tels que les connexions à une base de données et les appels à des API externes. N'oubliez pas d'effacer les surcharges après les tests.


Résumé

  • UtilisationTestClientTester directement l'application FastAPI sans démarrer de serveur.
  • Prend en charge le test de toutes les méthodes HTTP, y compris GET, POST, PUT, DELETE, etc.
  • Peut tester les paramètres de requête, les en-têtes de requête, les corps de requête, les réponses d'exception, etc.
  • Utilisationapp.dependency_overridesSurcharger les dépendances dans les tests
  • Avec pytest, vous pouvez facilement organiser et exécuter des tests.
autres extensions