Beachten Sie, dass die Testfunktionen normal def und nicht async def sind.
Und die Anrufe an den Client sind ebenfalls normale Anrufe, die nicht await verwenden.
Dadurch können Sie pytest ohne Komplikationen direkt nutzen.
Technische Details
Sie könnten auch from starlette.testclient import TestClient verwenden.
FastAPI stellt denselben starlette.testclient auch via fastapi.testclient bereit, als Annehmlichkeit für Sie, den Entwickler. Es kommt aber tatsächlich direkt von Starlette.
Tipp
Wenn Sie in Ihren Tests neben dem Senden von Anfragen an Ihre FastAPI-Anwendung auch async-Funktionen aufrufen möchten (z. B. asynchrone Datenbankfunktionen), werfen Sie einen Blick auf die Async-Tests im Handbuch für fortgeschrittene Benutzer.
Dann könnten Sie eine Datei test_main.py mit Ihren Tests haben. Sie könnte sich im selben Python-Package befinden (dasselbe Verzeichnis mit einer __init__.py-Datei):
Anschließend könnten Sie test_main.py mit den erweiterten Tests aktualisieren:
fromfastapi.testclientimportTestClientfrom.mainimportappclient=TestClient(app)deftest_read_item():response=client.get("/items/foo",headers={"X-Token":"coneofsilence"})assertresponse.status_code==200assertresponse.json()=={"id":"foo","title":"Foo","description":"There goes my hero",}deftest_read_item_bad_token():response=client.get("/items/foo",headers={"X-Token":"hailhydra"})assertresponse.status_code==400assertresponse.json()=={"detail":"Invalid X-Token header"}deftest_read_nonexistent_item():response=client.get("/items/baz",headers={"X-Token":"coneofsilence"})assertresponse.status_code==404assertresponse.json()=={"detail":"Item not found"}deftest_create_item():response=client.post("/items/",headers={"X-Token":"coneofsilence"},json={"id":"foobar","title":"Foo Bar","description":"The Foo Barters"},)assertresponse.status_code==200assertresponse.json()=={"id":"foobar","title":"Foo Bar","description":"The Foo Barters",}deftest_create_item_bad_token():response=client.post("/items/",headers={"X-Token":"hailhydra"},json={"id":"bazz","title":"Bazz","description":"Drop the bazz"},)assertresponse.status_code==400assertresponse.json()=={"detail":"Invalid X-Token header"}deftest_create_existing_item():response=client.post("/items/",headers={"X-Token":"coneofsilence"},json={"id":"foo","title":"The Foo ID Stealers","description":"There goes my stealer",},)assertresponse.status_code==409assertresponse.json()=={"detail":"Item already exists"}
Wenn Sie möchten, dass der Client Informationen im Request übergibt und Sie nicht wissen, wie das geht, können Sie suchen (googeln), wie es mit httpx gemacht wird, oder sogar, wie es mit requests gemacht wird, da das Design von HTTPX auf dem Design von Requests basiert.
Dann machen Sie in Ihren Tests einfach das gleiche.
Z. B.:
Um einen Pfad- oder Query-Parameter zu übergeben, fügen Sie ihn der URL selbst hinzu.
Um einen JSON-Body zu übergeben, übergeben Sie ein Python-Objekt (z. B. ein dict) an den Parameter json.
Wenn Sie Formulardaten anstelle von JSON senden müssen, verwenden Sie stattdessen den data-Parameter.
Um Header zu übergeben, verwenden Sie ein dict im headers-Parameter.
Für Cookies ein dict im cookies-Parameter.
Weitere Informationen zum Übergeben von Daten an das Backend (mithilfe von httpx oder dem TestClient) finden Sie in der HTTPX-Dokumentation.
Info
Beachten Sie, dass der TestClient Daten empfängt, die nach JSON konvertiert werden können, keine Pydantic-Modelle.
Wenn Sie ein Pydantic-Modell in Ihrem Test haben und dessen Daten während des Testens an die Anwendung senden möchten, können Sie den jsonable_encoder verwenden, der in JSON-kompatibler Encoder beschrieben wird.