测试FastAPI中OAuth2PasswordRequestForm接口时返回400状态码问题排查
问题诊断与解决方案
看起来你的测试用例全部返回400的核心原因有两个:请求数据格式不匹配,以及mock函数的判断逻辑错误,咱们一步步来解决:
1. 请求数据格式错误:OAuth2PasswordRequestForm 解析的是表单数据,不是JSON
你的接口使用了OAuth2PasswordRequestForm作为依赖,这个类专门用于解析**application/x-www-form-urlencoded格式的表单数据**,而不是JSON或multipart/form-data。但你的测试代码里做了两个错误操作:
- 用
json.dumps(payload)把数据序列化成JSON字符串 - 手动设置
headers={"content-type": "multipart/form-data"}
FastAPI无法从这种格式里解析出OAuth2PasswordRequestForm对象,所以直接返回400错误(请求格式无效)。
2. Mock函数逻辑错误:判断条件和测试用例不匹配
你的mock函数mock_check_credentials里判断的是"email" in payload,但你的测试用例里的payload键是username,而且接口传递给check_credentials的是OAuth2PasswordRequestForm对象(它的属性是.username和.password),不是原始的payload字典。这会导致即使正确的请求发送过来,mock也会返回False,触发401错误。
修正后的测试代码
@pytest.mark.parametrize("payload, status_code", [ [{"username": "john", "password": "secret"}, status.HTTP_200_OK], [{"username": "john"}, status.HTTP_401_UNAUTHORIZED], [{"password": "secret"}, status.HTTP_401_UNAUTHORIZED], [{}, status.HTTP_401_UNAUTHORIZED] ]) def test_user_credentials(test_app: TestClient, monkeypatch, payload, status_code): async def mock_check_credentials(credentials: OAuth2PasswordRequestForm): # 检查OAuth2PasswordRequestForm对象的属性,而不是原始payload return hasattr(credentials, "username") and hasattr(credentials, "password") monkeypatch.setattr(user_repository, "check_credentials", mock_check_credentials) # 直接传递payload作为data参数,TestClient会自动处理为表单格式 response = test_app.post("/users/credentials", data=payload) assert response.status_code == status_code
关键修正点说明
- 请求发送方式:去掉
json.dumps和手动设置的headers,直接把payload字典传给data参数,TestClient会自动设置正确的Content-Type: application/x-www-form-urlencoded,让FastAPI能正确解析OAuth2PasswordRequestForm。 - Mock逻辑修正:mock函数接收的是
OAuth2PasswordRequestForm实例,所以要检查它的.username和.password属性是否存在(或者根据你的验证逻辑调整,比如判断具体值),而不是去检查原始payload里的键。
这样修改后,你的测试用例应该就能符合预期:第一个用例返回200,其余返回401了。
内容的提问来源于stack exchange,提问作者jossefaz
相关产品推荐
相关产品推荐

