[英]Error testing an endpoint that uploads a text file using FastAPI + pytest
我在 fastapi 應用程序中有一個端點,它執行以下操作:
.txt
)代碼:
upload.py
from app.services.file_upload import file_uploader
from fastapi import APIRouter, File, UploadFile
router = APIRouter(
prefix="/upload-file",
tags=["Upload File"],
responses={
200: {'description': 'Success'},
400: {'description': 'Bad Request'},
422: {'description': 'Unprocessable Entity'},
500: {'description': 'Internal Server Error'}
}
)
@router.post('/')
def upload_file(upload_file: UploadFile = File(
...,
description='Upload file'
)):
filename = upload_file.filename
file_content = upload_file.file
return file_uploader(filename, file_content)
檢查完成的代碼
file_upload.py
import io
from typing import BinaryIO, Dict
import boto3
from app.core.config import settings
from fastapi import HTTPException
def file_uploader(filename: str, file_content: BinaryIO) -> Dict[str, str]:
if not filename.lower().endswith('.txt'):
raise HTTPException(status_code=422, detail='Only .txt file allowed')
s3 = boto3.client('s3')
file_content = io.BytesIO(file_content.read())
s3.upload_fileobj(file_content, settings.S3_BUCKET, filename)
return {'message': 'File uploaded.'}
我想測試這個端點,看看上傳的文件是否是文本文件。
conftest.py
from typing import Generator
import pytest
from app.main import app
from fastapi.testclient import TestClient
@pytest.fixture(scope="module")
def client() -> Generator:
with TestClient(app) as c:
yield c
test_upload.py
import pytest
from fastapi import HTTPException
from fastapi.testclient import TestClient
def test_upload_file(client: TestClient):
test_file = 'test_file.docx'
files = {'file': ('test_file.docx', open(test_file, 'rb'))}
with pytest.raises(HTTPException) as err:
client.post('/api/v1/upload-file/', files=files)
assert err.value.status_code == 422
當我運行此代碼時,出現以下錯誤
FAILED app/tests/api/v1/test_upload.py::test_upload_file - Failed: DID NOT RAISE <class 'fastapi.exceptions.HTTPException'>
我在做什么錯誤?
HTTPException
應用程序中的 HTTPException 不會傳播出去,FastAPI 將捕獲它並使用它返回 HTTP 錯誤響應(否則,引發異常會導致整個應用程序崩潰)。
由於TestClient
所做的基本上只是像任何其他客戶端一樣調用您的 API,因此您要做的是測試您是否獲得了正確的錯誤響應。 類似的東西
import pytest
from fastapi.testclient import TestClient
def test_upload_file(client: TestClient):
test_file = 'test_file.docx'
files = {'file': ('test_file.docx', open(test_file, 'rb'))}
response = client.post('/api/v1/upload-file/', files=files)
assert response.status_code == 422
assert response.json() == {"detail": "Only .txt file allowed"}
我猜文件名有問題,在您的端點upload_file
是預期的,但在您的測試中,您傳遞了一個帶有file
名的 object。 所以你得到422 Unprocessable Entity
異常。 您可以輕松地自己調試它:
response = client.post('/api/v1/upload-file/', files=files)
print(response.json()) # {'detail': [{'loc': ['body', 'upload_file'], 'msg': 'field required', 'type': 'value_error.missing'}]}
因此,要解決您的問題,請傳遞預期的文件名:
files = {'upload_file': ('test_file.docx', open(test_file, 'rb'))}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.