如何编写pytest测试含datetime字段的FastAPI+Pydantic接口
解决FastAPI异步测试中datetime字段的序列化问题
直接给你几个可行的方案,不用修改Pydantic模型:
方案1:用Pydantic模型自带的json()方法处理
Pydantic模型的json()方法会自动把datetime类型序列化成符合ISO 8601标准的字符串,刚好匹配接口的校验要求。你可以先把模型实例转成JSON字符串,再解析成Python字典传给测试客户端的json参数:
import json from datetime import datetime from httpx import AsyncClient from your_module import MemberCreate, app async def test_create_member(): member_data = MemberCreate( name="张三", birth_date=datetime(1990, 1, 1) ) # 用Pydantic的json()方法处理后转成字典 payload = json.loads(member_data.json()) async with AsyncClient(app=app, base_url="http://test") as ac: response = await ac.post("/members/", json=payload) assert response.status_code == 200
方案2:手动转换datetime字段为ISO字符串
如果不想用Pydantic的json方法,也可以手动把datetime字段转成ISO格式的字符串,直接构造请求用的字典:
from datetime import datetime from httpx import AsyncClient from your_module import MemberCreate, app async def test_create_member(): birth_date = datetime(1990, 1, 1) payload = { "name": "张三", "birth_date": birth_date.isoformat() } async with AsyncClient(app=app, base_url="http://test") as ac: response = await ac.post("/members/", json=payload) assert response.status_code == 200
方案3:给测试客户端指定自定义JSON编码器
如果有大量测试用例需要处理datetime,可以给AsyncClient指定自定义的JSON编码器,用Pydantic的默认编码器来处理:
from datetime import datetime from httpx import AsyncClient from pydantic.json import pydantic_encoder from your_module import MemberCreate, app async def test_create_member(): member_data = MemberCreate( name="张三", birth_date=datetime(1990, 1, 1) ) # 初始化客户端时指定json_encoder为pydantic_encoder async with AsyncClient( app=app, base_url="http://test", json_encoder=pydantic_encoder ) as ac: # 直接传模型的dict()结果就行 response = await ac.post("/members/", json=member_data.dict()) assert response.status_code == 200
为什么之前的方法不行?
- 直接传
member_data.dict():里面的birth_date是datetime对象,httpx的默认JSON编码器无法序列化,所以报错。 - 用
json.dumps()转成字符串后直接传:测试客户端的json参数需要的是Python对象,不是JSON字符串,你传字符串的话会被当成普通文本,接口解析时自然会触发Pydantic的校验错误(因为期望的是JSON对象,不是字符串)。
内容的提问来源于stack exchange,提问作者Gregorio Castillo
相关产品推荐
相关产品推荐

