如何在pytest中编写multipart/form-data格式的文件上传接口测试?
刚好我之前做过类似的pytest测试照片上传接口的需求,给你分享下具体的实现步骤和踩坑点,应该能解决你提交photo_file的问题~
编写pytest测试照片上传POST接口的步骤
1. 先确认依赖
首先确保你已经安装了必要的包:
pip install pytest requests pillow pymongo
(pillow是用来生成临时测试图片的,如果你有现成的测试图也可以不用;pymongo用来验证MongoDB的数据存储)
2. 编写测试前置Fixtures
用pytest的fixture来统一管理测试资源,避免重复代码:
import pytest import os from PIL import Image from pymongo import MongoClient from your_project.models import Photo # 替换成你项目中Photo类的导入路径 @pytest.fixture(scope="module") def test_image(): # 生成一个临时测试图片(或者直接用你本地的测试图片路径) temp_img_path = "temp_test_photo.jpg" # 创建一个100x100的红色测试图 img = Image.new('RGB', (100, 100), color='crimson') img.save(temp_img_path) yield temp_img_path # 测试完成后清理临时文件 if os.path.exists(temp_img_path): os.remove(temp_img_path) @pytest.fixture(scope="module") def test_mongo_db(): # 连接测试专用的MongoDB实例!绝对不要用生产库! client = MongoClient("mongodb://localhost:27017/") test_db = client["test_photo_service"] yield test_db # 测试结束后清空测试集合,避免污染数据 test_db.photos.delete_many({}) client.close()
3. 核心测试用例实现
针对你的multipart/form-data上传接口,核心是正确构造files参数来传递图片文件,同时用data传递附加信息:
import requests def test_photo_upload_success(test_image, test_mongo_db): # 替换成你的实际接口地址 api_url = "http://localhost:5000/api/photos/upload" # 附加信息:完全按照Swagger定义的字段来传 form_data = { "title": "海边日落测试图", "description": "这是一张用于pytest测试的照片", "category": "风景" } # 关键:构造文件参数,key必须和Swagger中定义的参数名一致(比如你说的photo_file) # 注意要用rb模式打开文件 with open(test_image, "rb") as img_file: files = { "photo_file": (os.path.basename(test_image), img_file, "image/jpeg") } # 发送POST请求:data传表单字段,files传文件 response = requests.post(api_url, data=form_data, files=files) # 第一步:断言响应状态码(一般创建成功是201) assert response.status_code == 201, f"上传失败,响应内容:{response.text}" # 第二步:解析响应数据,验证返回的字段 response_json = response.json() assert "photo_id" in response_json, "响应未返回photo_id" uploaded_photo_id = response_json["photo_id"] # 第三步:验证MongoDB中是否正确存储了数据 stored_photo = test_mongo_db.photos.find_one({"_id": uploaded_photo_id}) assert stored_photo is not None, "照片未存入MongoDB" # 验证附加信息是否正确 assert stored_photo["title"] == form_data["title"] assert stored_photo["description"] == form_data["description"] # 如果你的Photo类可以直接映射数据库文档,也可以用类来验证 photo_instance = Photo(**stored_photo) assert photo_instance.category == form_data["category"]
4. 常见问题排查(针对你遇到的photo_file提交问题)
- 参数key不匹配:一定要确保
files中的key和Swagger里定义的上传参数名完全一致,比如Swagger里写的是photo_file就不能写成file或者image - 文件打开模式错误:必须用
rb(二进制读)模式打开图片,用r模式会导致文件内容损坏 - 接口需要认证:如果你的接口需要token或者权限验证,记得在请求头里加上:
headers = {"Authorization": "Bearer your_test_token"} response = requests.post(api_url, data=form_data, files=files, headers=headers) - 测试数据库配置错误:确保你连接的是测试库,测试后一定要清理数据,避免影响后续测试
如果是用Flask/Django的测试客户端
如果你的服务是Flask或者Django,用框架自带的测试客户端写法会略有不同,以Flask为例:
from your_project.app import create_app @pytest.fixture(scope="module") def flask_client(): app = create_app(config="testing") with app.test_client() as client: yield client def test_flask_photo_upload(flask_client, test_image): with open(test_image, "rb") as img_file: # Flask测试客户端中,文件需要用元组格式:(文件名, 文件对象, 内容类型) data = { "title": "Flask测试图", "photo_file": (os.path.basename(test_image), img_file, "image/jpeg") } response = flask_client.post("/api/photos", data=data, content_type="multipart/form-data") assert response.status_code == 201 # 后续断言逻辑和之前一致
内容的提问来源于stack exchange,提问作者urgent123
相关产品推荐
相关产品推荐

