Here's a self-contained, minimal, reproducible, example with my use case:
from fastapi import FastAPI
router = FastAPI()
@router.post("/_config")
def create_index_config(upload_file: UploadFile = File(...)):
config = settings.reads()
created_config_file: Path = Path(config.config_dir, upload_file.filename)
try:
with created_config_file.open('wb') as write_file:
shutil.copyfileobj(upload_file.file, write_file)
except Exception as err:
raise HTTPException(detail=f'{err} encountered while uploading {upload_file.filename}',
status_code=HTTPStatus.INTERNAL_SERVER_ERROR)
finally:
upload_file.file.close()
return JSONResponse({"message": f'uploaded config {upload_file.filename}'})
I'm just trying to test against an endpoint that uses uploadfile and I can't find how to send a json file to fastapi
def test_one():
_test_upload_file = <path to file>
with TestClient(app) as client:
# TODO how to upload a file
response = client.post('/_config',
data= <assuming something goes here ???> )
assert response.status_code == HTTPStatus.CREATED
data=_test_upload_file.open('rb') yields a 422 error
I have also tried this and get a 422 error
I've solved this yesterday on gitter. Could you search for "UploadFile" there? I'm busy now. I can post it here later if I remember.. or you can check there and post the solution here as well to help others.
Here you have: https://stackoverflow.com/questions/60783222/how-to-test-a-fastapi-api-endpoint-that-consumes-images
Example:
with open(fpath, "wb") as f:
response = client.post("/", files={"file": ("filename", f, "image/jpeg")})
Here you have: https://stackoverflow.com/questions/60783222/how-to-test-a-fastapi-api-endpoint-that-consumes-images
Example:
with open(fpath, "wb") as f: response = client.post("/", files={"file": ("filename", f, "image/jpeg")})
I saw that but couldn't get it to work with my application
On gitter I found this
def test_upload(tmp_path):
url = app.url_path_for("create_upload_files")
with TestClient(app) as client:
f = tmp_path / 'fileupload'
with open(f, 'wb') as tmp:
tmp.write(b'upload this')
with open(f, 'rb') as tmp:
files = {'files': tmp}
response = client.post(url, files=files)
assert response.status_code == 200
But that gives a 422 error when I try it in my code
with TestClient(app) as client:
# TODO how to upload a file
with _test_upload_file.open('rb') as tmp:
files = {'files': tmp}
response = client.post('/_config',
files=files)
assert response.status_code == HTTPStatus.CREATED
Big dumb on my part..
Working test:
_test_upload_file = Path('/usr/src/app/tests/files', 'new-index.json')
_files = {'upload_file': _test_upload_file.open('rb')}
with TestClient(app) as client:
response = client.post('/_config',
files=_files)
assert response.status_code == HTTPStatus.CREATED
# remove the test file from the config directory
_copied_file = Path('/usr/src/app/config', 'new-index.json')
_copied_file.unlink()
I previously had the upload_file in the test named files -- FYSA that name must match the parameter of your endpoint, in my case it's upload_file so files wasn't working
Follow up with the code from Gitter also worked, thanks :)
Thanks for the help here @Kludex ! :clap: :bow:
Thanks for reporting back and closing the issue @mwilson8 :+1:
Here you have: https://stackoverflow.com/questions/60783222/how-to-test-a-fastapi-api-endpoint-that-consumes-images
Example:
with open(fpath, "wb") as f: response = client.post("/", files={"file": ("filename", f, "image/jpeg")})
This didn't work for me. I had to change the with open(fpath, "wb") as f to with open(fpath, "rb") as f:
Using read instead of write operation here works :)
A slight follow up, how do you test against the actual function as opposed to the endpoint?
Working test against the endpoint:
_test_upload_file = Path('filepath')
_files = {'upload_file': _test_upload_file.open('rb')}
with TestClient(app) as client:
response = client.post('/_config',
files=_files,
)
assert response.status_code == HTTPStatus.OK
But I also want to test with
response = service.function_within_endpoint(upload_file=<...what goes here...>)
Have you tried passing an instance of UploadFile?
Most helpful comment
Thanks for the help here @Kludex ! :clap: :bow:
Thanks for reporting back and closing the issue @mwilson8 :+1: