0

I have a simple FastAPI setup as below,

# main.py

from fastapi import FastAPI

app = FastAPI()


@app.on_event("shutdown")
def app_shutdown():
    with open("shutdown-test-file.txt", "w") as fp:
        fp.write("FastAPI app has been terminated")


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

How can I write (unit)test for this app_shutdown(...) functionality?


Related Posts

  • This SO post is also asking similar question, but, not in a "testing context"
  • The official doc has something similar, but, there is no example for on_event("shutdown")
JPG
  • 82,442
  • 19
  • 127
  • 206
  • Shouldn't the `on_event("shutdown")` be triggered just as the `on_event("startup")` in the example given in the doc? – MatsLindh Nov 27 '21 at 15:41
  • Unfortunately, No. – JPG Nov 27 '21 at 16:38
  • Might be helpful https://stackoverflow.com/questions/65051581/how-to-trigger-lifespan-startup-and-shutdown-while-testing-fastapi-app/65061155#65061155 – alex_noname Nov 27 '21 at 17:15
  • 2
    I just tested the official doc example and it works just fine with both `shutdown` and `startup`: `def test_foo(): with TestClient(app) as client: response = client.get('/')` triggers both the `@app.on_event("shutdown")` and the `@app.on_event("startup")` events. – MatsLindh Nov 27 '21 at 21:07
  • Unfortunately, it didn't work for me. Could you add a minimal test (for my situation) as an answer below? @MatsLindh – JPG Nov 28 '21 at 02:00
  • So is your problem that _the event isn't triggered_, or is the problem with testing the file write functionality? – MatsLindh Nov 28 '21 at 10:09
  • The `shutdown` event is getting called properly if I terminate the FastAPI server (not test client). But, I don't any such operations during my test run. – JPG Nov 28 '21 at 13:17
  • Same here, I got it working after wrapping with `with` (context manager) – sareno May 18 '22 at 06:43

1 Answers1

1

According to the documentation, you need to wrap it in the context manager (a with statement) to trigger the events, something like this:

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

If you use pytest, you can set up a fixture for it like this:

from main import app
from fastapi.testclient import TestClient

import pytest


@pytest.fixture
def client():
    with TestClient(app) as c:
        yield c


def test_read_main(client):
    response = client.get("/")
    assert response.status_code == 200
Triet Doan
  • 11,455
  • 8
  • 36
  • 69