Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

FastAPI - Dynamic response

  • A small step ahead generating part of the content of the response dynamically.

We also start using uv to manage packages. So you'll need to install uv before you try this.

Dependencies

[project]
name = "dynamic-response"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "fastapi[all]>=0.117.1",
    "pytest>=8.4.2",
]

You don't need to do any separate step of installing the dependencies, you can go ahead and run the code:

uv run fastapi dev main.py

the visit http://localhost:8000

In this example we use the datetime module to generate the current time. And return it as the value of the 'date' field.

from fastapi import FastAPI
import datetime

app = FastAPI()


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

Testing

The testing is going to be a bit trickier. After all we don't know what will be the exact time when someone runs the tests and thus we cannot compare the returned data to some exact expectation. In a more advanced example we might mock the time, but for now we'll just make our test a bit more forgiving. We'll only check if the returned data looks like a date and if can be converted to a datetime object.

We check if the JSON returns exactly the fields we are expecting. We need to sort the fields as we don't want to assume the exact order of the fields in the JSON.

  • We use an exact match for the text field.
  • For the date field first we use a rather simple regex to verify that the returned string looks like a timestamp.
  • Then we try to load it using the fromisoformat method.
from fastapi.testclient import TestClient
import re
import datetime

from main import app

client = TestClient(app)


def test_read_main():
    response = client.get("/")
    assert response.status_code == 200
    assert response.headers["content-type"] == "application/json"

    resp = response.json()
    assert sorted(resp.keys()) == ['date', 'message']
    assert "Hello World", resp["message"]
    assert re.search(r'^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{6}$', resp["date"], re.ASCII)
    assert datetime.datetime.fromisoformat(resp["date"])

In order to run the tests we only need to execute:

uv run pytest

  • datetime
  • re
  • pytest