FastAPI TestClient发送form-data类型POST请求失败的问题排查
问题
使用FastAPI的from fastapi.testclient import TestClient编写登录接口单元测试时,尝试发送form-data格式POST请求到/api/login接口,但无法像启动应用后那样获取token响应。相关代码及Postman请求示例如下:
测试代码
def test_login_api_returns_token(session,client): form_data = { "username": "mike@gmail.com", "password": "mike" } response = client.post( "/api/login", data=form_data, headers={"content-type": "multipart/form-data"} # headers={"content-type": "application/x-www-form-urlencoded"} ) result = response.json() assert response.status_code == 200
登录接口代码(api/login.py)
@router.post("/login") async def user_login(form_data: OAuth2PasswordRequestForm = Depends(), session: Session = Depends(get_session)): user = authenticated_user(form_data.username, form_data.password, session) user = user[0] if not user: raise token_exception() token_expires = timedelta(minutes=120) token = create_access_token(username=user.username, user_id=user.id, expires_delta=token_expires) token_exp = jwt.decode(token, SECRET, algorithms=[ALGORITHM]) return { "status_code": status.HTTP_200_OK, "data":{ "username": user.username, "token": token, "expiry": token_exp['exp'], "user_id": user.id } }
Postman请求示例

解决方案
问题出在TestClient的请求发送方式上:OAuth2PasswordRequestForm默认期望application/x-www-form-urlencoded格式请求,而非multipart/form-data,且手动指定content-type会干扰TestClient的自动处理。按以下方式修改测试代码即可:
- 移除手动设置的
Content-Type头:TestClient会根据data参数自动设置正确的application/x-www-form-urlencoded头,无需手动指定。 - 直接用
data参数传递表单数据:TestClient会自动完成数据编码。
修改后的测试代码:
def test_login_api_returns_token(session, client): form_data = { "username": "mike@gmail.com", "password": "mike" } response = client.post( "/api/login", data=form_data ) result = response.json() assert response.status_code == 200
补充说明
OAuth2PasswordRequestForm是FastAPI专为OAuth2密码模式设计的表单依赖,内部已完成application/x-www-form-urlencoded格式的请求解析。- Postman选
form-data能成功,是因为OAuth2PasswordRequestForm基于的RequestForm同时支持两种格式,但测试时用贴合依赖设计的application/x-www-form-urlencoded更直接。 - 若确实需要发送
multipart/form-data请求,不要手动设置content-type,改用files参数传递字段即可(即便没有文件),但此场景下完全没必要。
内容的提问来源于stack exchange,提问作者code_10
相关产品推荐
相关产品推荐

