How to Test File Upload in FastAPI: Simple Guide with Example
To test file upload in
FastAPI, use TestClient from fastapi.testclient and send a POST request with the file data as files={'file': ('filename', file_bytes, 'content_type')}. This simulates uploading a file to your endpoint and lets you verify the response.Syntax
Testing file upload in FastAPI involves sending a POST request with a files parameter to the test client. The files parameter is a dictionary where the key is the form field name and the value is a tuple containing the filename, file content bytes, and the content type.
- files={'file': ('filename', file_bytes, 'content_type')}: This simulates the file upload.
- TestClient(app): Creates a test client for your FastAPI app.
- client.post(url, files=files): Sends the POST request with the file.
python
from fastapi.testclient import TestClient client = TestClient(app) response = client.post( "/upload", files={"file": ("test.txt", b"file content", "text/plain")} )
Example
This example shows a FastAPI app with a file upload endpoint and a test that uploads a file using TestClient. The test checks if the upload was successful by asserting the response status and content.
python
from fastapi import FastAPI, File, UploadFile from fastapi.testclient import TestClient app = FastAPI() @app.post("/upload") async def upload_file(file: UploadFile = File(...)): content = await file.read() return {"filename": file.filename, "content_size": len(content)} client = TestClient(app) def test_upload_file(): file_content = b"Hello, FastAPI file upload test!" response = client.post( "/upload", files={"file": ("hello.txt", file_content, "text/plain")} ) assert response.status_code == 200 json_resp = response.json() assert json_resp["filename"] == "hello.txt" assert json_resp["content_size"] == len(file_content) # Run the test function if __name__ == "__main__": test_upload_file() print("Test passed successfully.")
Output
Test passed successfully.
Common Pitfalls
- Forgetting to use
files=in the test client POST request instead ofdata=causes the file not to be sent correctly. - Not providing the filename or content type in the tuple can lead to unexpected behavior.
- Trying to read the file synchronously in the endpoint instead of using
await file.read()when the endpoint is async. - Not using
UploadFiletype in the endpoint parameter, which is designed for file uploads.
python
from fastapi import FastAPI, File from fastapi.testclient import TestClient app = FastAPI() # Wrong: Using bytes directly instead of UploadFile @app.post("/upload_wrong") def upload_wrong(file: bytes = File(...)): return {"size": len(file)} client = TestClient(app) # Wrong test: Using data= instead of files= response_wrong = client.post("/upload_wrong", data={"file": ("test.txt", b"content")}) # Right test: response_right = client.post( "/upload_wrong", files={"file": ("test.txt", b"content", "text/plain")} ) assert response_right.status_code == 200
Quick Reference
Remember these key points when testing file uploads in FastAPI:
- Use
TestClientto simulate requests. - Send files with the
files=parameter as a dict with tuples. - Use
UploadFilein your endpoint for efficient file handling. - Always include filename and content type in the test upload.
Key Takeaways
Use TestClient with the files parameter to simulate file uploads in tests.
Always send files as tuples with filename, bytes content, and content type.
Define your endpoint parameter as UploadFile for async file reading.
Avoid using data= instead of files= when posting files in tests.
Check response status and content to verify successful upload.