I have a file called main.py
in which I put a POST
call with only one input parameter (integer). Simplified code is given below:
from fastapi import FastAPI
app = FastAPI()
@app.post("/do_something/")
async def do_something(process_id: int):
# some code
return {"process_id": process_id}
Now, if I run the code for the test, saved in the file test_main.py
, that is:
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_do_something():
response = client.post(
"/do_something/",
json={
"process_id": 16
}
)
return response.json()
print(test_do_something())
I get:
{'detail': [{'loc': ['query', 'process_id'], 'msg': 'field required', 'type': 'value_error.missing'}]}
I can't figure out what the mistake is. It is necessary that it remains a POST
call.
The error, basically, says that the required query parameter process_id
is missing. The reason for that error is that you send a POST request with request body
, i.e., JSON payload; however, your endpoint expects a query parameter.
To receive the data in JSON format instead, one needs to create a Pydantic BaseModel—as shown below—and send the data from the client in the same way you already do.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
process_id: int
@app.post("/do_something")
async def do_something(item: Item):
return item
Test the above as shown in your question:
def test_do_something():
response = client.post("/do_something", json={"process_id": 16})
return response.json()
If, however, you had to pass a query parameter, then you would create an endpoint in the same way you did, that is:
@app.post("/do_something")
async def do_something(process_id: int):
return {"process_id": process_id}
but on client side, you would need to add the parameter to the URL itself, as described in the documentation (e.g., "/do_something?process_id=16"
), or use the params
attribute and as shown below:
def test_do_something():
response = client.post("/do_something", params={"process_id": 16})
return response.json()
Alternatively, another way to pass JSON data when having a single body parameter is to use Body(..., embed=True)
, as shown below:
@app.post("/do_something")
def do_something(process_id: int = Body(..., embed=True)):
return process_id
For more details and options on how to post JSON data in FastAPI, please have a look at this answer and this answer.