I have a FastAPI app with a route prefix as /api/v1
.
When I run the test it throws 404
. I see this is because the TestClient
is not able to find the route at /ping
, and works perfectly when the route in the test case is changed to /api/v1/ping
.
Is there a way in which I can avoid changing all the routes in all the test functions as per the prefix? This seems to be cumbersome as there are many test cases, and also because I dont want to have a hard-coded dependency of the route prefix in my test cases. Is there a way in which I can configure the prefix in the TestClient
just as we did in app
, and simply mention the route just as mentioned in the routes.py
?
routes.py
from fastapi import APIRouter
router = APIRouter()
@router.get("/ping")
async def ping_check():
return {"msg": "pong"}
main.py
from fastapi import FastAPI
from routes import router
app = FastAPI()
app.include_router(prefix="/api/v1")
In the test file I have:
test.py
from main import app
from fastapi.testclient import TestClient
client = TestClient(app)
def test_ping():
response = client.get("/ping")
assert response.status_code == 200
assert response.json() == {"msg": "pong"}
Figured out a workaround for this.
The TestClient
has an option to accept a base_url
, which is then urljoin
ed with the route path
. So I appended the route prefix to this base_url
.
url = urljoin(self.base_url, url)
However, there is a catch to this - urljoin
concatenates as expected only when the base_url
ends with a /
and the path
does not start with a /
. This SO answer explains it well.
This resulted in the below change:
test.py
from main import app, ROUTE_PREFIX
from fastapi.testclient import TestClient
client = TestClient(app)
client.base_url += ROUTE_PREFIX # adding prefix
client.base_url = client.base_url.rstrip("/") + "/" # making sure we have 1 and only 1 `/`
def test_ping():
response = client.get("ping") # notice the path no more begins with a `/`
assert response.status_code == 200
assert response.json() == {"msg": "pong"}