You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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请求示例

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:35:49