`RequestValidationError` is raised when testing, instead of returing `422` response
See original GitHub issueFirst Check
- I added a very descriptive title to this issue.
- I used the GitHub search to find a similar issue and didn’t find it.
- I searched the FastAPI documentation, with the integrated search.
- I already searched in Google “How to X in FastAPI” and didn’t find any information.
- I already read and followed all the tutorial in the docs and didn’t find an answer.
- I already checked if it is not related to FastAPI but to Pydantic.
- I already checked if it is not related to FastAPI but to Swagger UI.
- I already checked if it is not related to FastAPI but to ReDoc.
Commit to Help
- I commit to help with one of those options 👆
Example Code
import uuid
from fastapi import FastAPI, APIRouter, Header, HTTPException
from fastapi.testclient import TestClient
from pydantic import BaseModel
# Models and CRUD
class Item(BaseModel):
id: int
content: str
def crud_get_items():
# This function lies in a separate module
return [
Item(id=1, content="First item"),
Item(id=2, content="Second item"),
]
# App
app = APIRouter()
@app.get("/")
async def get_items(user_id: str = Header()):
data = crud_get_items()
if not len(data): # This is redundant in the example, but exist in "normal" codebase
raise HTTPException(status_code=404, detail="No items found")
return data
# Tests
client = TestClient(app)
def test_get_items():
headers = {"user-id": str(uuid.uuid4())}
res = client.get("/", headers=headers)
assert res.status_code == 200
def test_get_items_without_userid():
res = client.get("/")
assert res.status_code == 422
Description
When testing my app I noticed, that sending request to router without header parameter set, I get RequestValidationError
instead of 422
status code. This doesn’t happen, when using FastAPI
instead of APIRouter
.
One could say, that an easy fix to this is to wrap the second test code in pytest.raises()
, but this will only execute the client.get
while skipping all asserts the test has.
from fastapi.exceptions import RequestValidationError
def test_get_items_without_userid():
with pytest.raises(RequestValidationError):
res = client.get("/") # This line will execute
assert res.status_code == 422 # This line won't (and any below)
Operating System
Windows
Operating System Details
Windows 10, 21H2
FastAPI Version
0.85.0
Python Version
Python 3.10.4
Additional Context
No response
Issue Analytics
- State:
- Created a year ago
- Comments:6 (3 by maintainers)
Top Results From Across the Web
[Bug] 422 Response Not Being Used For Validation ... - GitHub
I have unit tests that validate an endpoint, so I am using Prism like ... it to return the server response instead of...
Read more >Handling Errors - FastAPI
These handlers are in charge of returning the default JSON responses when you raise an HTTPException and when the request has invalid data....
Read more >FastAPI - Pydantic - Value Error Raises Internal Server Error
RequestValidationError is a sub-class of Pydantic's ValidationError . The result of this is that a standard Validation error raised during ...
Read more >3 Ways to Handle Errors in FastAPI That You Need to Know
Notice that the status in the response changed based on what we specified. 2. Create a Custom Exception #. If you are feeling...
Read more >Complex Request Validation in FastAPI with Pydantic
... day (Saturday or Sunday), return a request-validation error response. ... and day_number > 365: return JSONResponse( status_code=422, ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
The
TestClient
is created to testStarlette
applications, and by extension you can use it to testFastAPI
applications. It is not designed to test Starlette’sRouter
or FastAPI’sAPIRouter
directly. As you have experienced, it can yield unexpected results. Most notably: The difference between sending a request to aFastAPI
application and sending a request to theAPIRouter
directly (using it as an ASGI application on its own), is that no middleware is executed when doing the latter.And by default (and design), there are always at least 2 middleware present in your FastAPI application (which will not be present in your
APIRouter
instance: one that catches and handles exceptions likeHTTPException
and one (the very last one) that handles any uncaught exception and returns aHTTP 500 Internal Server Error
to ensure your server keeps running.So, when using
APIRouter
directly in yourTestClient
, any raisedHTTPException
s will not result in a proper response, rather than actually raised (and unhandled) exception.So, to answer your question:
The behaviour that you are experiencing is by design, and when testing an
APIRouter
one should keep in mind thatFastAPI + APIRouter
has different behaviour than just theAPIRouter
as an ASGI application on its own.Thanks for the help here @JarroVGIT ! 👏 You rock! 🙇
Thanks for reporting back and closing the issue @jkazimierczak 👍