如何用aiohttp测试基于Pydantic的FastAPI接口?
解决aiohttp测试FastAPI时Pydantic模型序列化与422验证问题
问题原因与对应解决方案
1. Pydantic模型对象无法JSON序列化
aiohttp的ClientSession.post()方法中json参数只接受Python原生可JSON序列化的类型(比如字典、列表),直接传递Pydantic模型对象会触发TypeError,因为Python默认的JSON序列化器无法识别Pydantic模型结构。
解决方法:
使用Pydantic模型的内置方法将对象转换为字典:
- Pydantic v2:调用
model_dump()方法 - Pydantic v1:调用
dict()方法
2. 传递普通字典返回422错误
422错误的核心原因是请求格式与FastAPI接口期望不匹配:FastAPI的接口参数声明为user: UsersScheme时,默认期望接收application/json格式的请求体,而如果使用data参数传递字典,aiohttp会将数据以application/x-www-form-urlencoded(表单)格式发送,导致Pydantic无法正确解析验证。
解决方法:
确保使用json参数传递字典,而非data参数,aiohttp会自动设置正确的Content-Type: application/json请求头。
修改后的测试用例代码
from src.backend.users.schemas import UsersScheme from tests.test_db import test_database_preparation import aiohttp class TestUserAuthentication: async def test_user_registration(self, test_database_preparation): fake_user = { "username": "test", "non_hashed_password": "test" } # 方法1:使用Pydantic模型转换后传递 user: UsersScheme = UsersScheme(**fake_user) async with aiohttp.ClientSession() as client_session: # Pydantic v2用model_dump(),v1用dict() resp = await client_session.post(url="http://localhost:8000/users/register", json=user.model_dump()) assert resp.status == 200 # 方法2:直接传递字典(需确保键名与模型完全匹配) # async with aiohttp.ClientSession() as client_session: # resp = await client_session.post(url="http://localhost:8000/users/register", json=fake_user) # assert resp.status == 200
额外注意事项
- 确保测试环境已安装
pytest-asyncio插件,否则无法运行异步测试用例,安装命令:pip install pytest-asyncio - 确认FastAPI服务在测试前已启动,且测试请求的URL与服务实际地址一致
内容的提问来源于stack exchange,提问作者PYTHON TERMINATOR
相关产品推荐
相关产品推荐

