[英]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.