[英]Error testing an endpoint that uploads a text file using FastAPI + pytest
I have an endpoint in fastapi app that does the following:我在 fastapi 应用程序中有一个端点,它执行以下操作:
.txt
)检查文件是否为文本文件 ( .txt
)The codes:代码:
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)
The code where the check is done检查完成的代码
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.'}
I want to test this endpoint to see if the file being uploaded is a text file or not.我想测试这个端点,看看上传的文件是否是文本文件。
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
When I run this code, I get the following error当我运行此代码时,出现以下错误
FAILED app/tests/api/v1/test_upload.py::test_upload_file - Failed: DID NOT RAISE <class 'fastapi.exceptions.HTTPException'>
What is the mistake I am doing?我在做什么错误?
The HTTPException
in the FastAPI app will not propagate out, FastAPI will catch it and use it to return an HTTP error response (otherwise, raising an exception would crash your entire app). HTTPException
应用程序中的 HTTPException 不会传播出去,FastAPI 将捕获它并使用它返回 HTTP 错误响应(否则,引发异常会导致整个应用程序崩溃)。
Since what TestClient
is doing is essentially just calling your API as any other client would, what you want to do is test that you get the correct error response.由于TestClient
所做的基本上只是像任何其他客户端一样调用您的 API,因此您要做的是测试您是否获得了正确的错误响应。 Something along the lines of类似的东西
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"}
I guess there's a problem with the file name, in your endpoint upload_file
is expected, but in your test, you're passing an object with file
name.我猜文件名有问题,在您的端点upload_file
是预期的,但在您的测试中,您传递了一个带有file
名的 object。 So you get 422 Unprocessable Entity
exception.所以你得到422 Unprocessable Entity
异常。 You can easily debug it yourself:您可以轻松地自己调试它:
response = client.post('/api/v1/upload-file/', files=files)
print(response.json()) # {'detail': [{'loc': ['body', 'upload_file'], 'msg': 'field required', 'type': 'value_error.missing'}]}
So, to fix your problem pass the expected file name:因此,要解决您的问题,请传递预期的文件名:
files = {'upload_file': ('test_file.docx', open(test_file, 'rb'))}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.