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.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.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 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.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.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é
- Utilisation
TestClientTester 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.
- Utilisation
app.dependency_overridesSurcharger les dépendances dans les tests - Avec pytest, vous pouvez facilement organiser et exécuter des tests.