Skip to content

Testing

Thanks to Starlette's TestClient, testing FastAPI applications is easy and enjoyable.

It is based on Requests, so it's very familiar and intuitive.

With it, you can use pytest directly with FastAPI.

Using TestClient

Import TestClient from starlette.testclient.

Create a TestClient passing to it your FastAPI.

Create functions with a name that starts with test_ (this is standard pytest conventions).

Use the TestClient object the same way as you do with requests.

Write simple assert statements with the standard Python expressions that you need to check (again, standard pytest).

from fastapi import FastAPI
from starlette.testclient import TestClient

app = FastAPI()


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


client = TestClient(app)


def test_read_main():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"msg": "Hello World"}

Tip

Notice that the testing functions are normal def, not async def.

And the calls to the client are also normal calls, not using await.

This allows you to use pytest directly without complications.

Separating tests

In a real application, you probably would have your tests in a different file.

And your FastAPI application might also be composed of several files/modules, etc.

FastAPI app file

Let's say you have a file main.py with your FastAPI app:

from fastapi import FastAPI

app = FastAPI()


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

Testing file

Then you could have a file test_main.py with your tests, and import your app from the main module (main.py):

from starlette.testclient import TestClient

from .main import app

client = TestClient(app)


def test_read_main():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"msg": "Hello World"}

Testing WebSockets

You can use the same TestClient to test WebSockets.

For this, you use the TestClient in a with statement, connecting to the WebSocket:

from fastapi import FastAPI
from starlette.testclient import TestClient
from starlette.websockets import WebSocket

app = FastAPI()


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


@app.websocket_route("/ws")
async def websocket(websocket: WebSocket):
    await websocket.accept()
    await websocket.send_json({"msg": "Hello WebSocket"})
    await websocket.close()


def test_read_main():
    client = TestClient(app)
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"msg": "Hello World"}


def test_websocket():
    client = TestClient(app)
    with client.websocket_connect("/ws") as websocket:
        data = websocket.receive_json()
        assert data == {"msg": "Hello WebSocket"}

Testing Events, startup and shutdown

When you need your event handlers (startup and shutdown) to run in your tests, you can use the TestClient with a with statement:

from fastapi import FastAPI
from starlette.testclient import TestClient

app = FastAPI()

items = {}


@app.on_event("startup")
async def startup_event():
    items["foo"] = {"name": "Fighters"}
    items["bar"] = {"name": "Tenders"}


@app.get("/items/{item_id}")
async def read_items(item_id: str):
    return items[item_id]


def test_read_items():
    with TestClient(app) as client:
        response = client.get("/items/foo")
        assert response.status_code == 200
        assert response.json() == {"name": "Fighters"}

Run it

After that, you just need to install pytest:

pip install pytest

It will detect the files and tests automatically, execute them, and report the results back to you.

Run the tests with:

pytest