Flask+Auth0单元测试请求无200状态码及预期行为问题排查
解决Flask+Auth0单元测试中302重定向问题
核心问题分析
测试请求被重定向,说明@requires_auth装饰器未认可传入的Bearer令牌,未通过认证触发了Auth0的重定向逻辑;同时HTTP连接代码存在语法错误与连接管理问题,导致CannotSendRequest和socket.gaierror错误。
步骤1:修正令牌获取代码
原代码存在引号不匹配、硬编码JSON易出错、未关闭连接等问题,修正后:
import http.client import json # 修正域名格式与引号问题 conn = http.client.HTTPSConnection("api-name.auth0.com") # 用json.dumps生成payload,避免转义错误 payload = json.dumps({ "client_id": "MY_CLIENT_ID", "client_secret": "MY_CLIENT_SECRET", "audience": "MY_AUD", "grant_type": "client_credentials" }) headers = {'content-type': "application/json"} conn.request("POST", "/oauth/token", payload, headers) res = conn.getresponse() data = res.read() conn.close() # 关闭连接,避免CannotSendRequest错误 decoded_data = data.decode("utf-8") response_json = json.loads(decoded_data) access_token = response_json.get('access_token') auth_headers = {'Authorization': f'Bearer {access_token}'}
步骤2:修正Pytest测试逻辑
问题根源
路由代码直接从session读取用户信息,但client credentials模式的令牌是机器身份,不会自动填充session;同时测试中重复设置认证头可能导致冲突。
方案A:Mock认证装饰器(单元测试推荐)
单元测试聚焦路由逻辑,跳过真实Auth0校验:
import pytest from unittest.mock import patch @pytest.fixture def client(): app.testing = True # Mock requires_auth装饰器,直接返回原函数 with patch('your_app_module.requires_auth', lambda x: x): with app.test_client() as client: # 模拟session中的用户信息,匹配路由取值 with client.session_transaction() as sess: sess[constants.PROFILE_KEY] = { "user_id": "test-user-123" } yield client def test_route(client): response = client.get("/route") assert b"<h2>Upload</h2>" in response.data assert response.status_code == 200
方案B:适配真实Auth0认证(集成测试用)
若需真实认证,需确保@requires_auth支持client credentials令牌并填充session,同时正确传递请求头:
@pytest.fixture def auth_headers(): # 生成认证令牌 import http.client import json conn = http.client.HTTPSConnection("api-name.auth0.com") payload = json.dumps({ "client_id": "MY_CLIENT_ID", "client_secret": "MY_CLIENT_SECRET", "audience": "MY_AUD", "grant_type": "client_credentials" }) headers = {'content-type': "application/json"} conn.request("POST", "/oauth/token", payload, headers) res = conn.getresponse() data = res.read() conn.close() response_json = json.loads(data.decode("utf-8")) access_token = response_json.get('access_token') return {'Authorization': f'Bearer {access_token}'} @pytest.fixture def client(): app.testing = True with app.test_client() as client: yield client def test_route(client, auth_headers): response = client.get("/route", headers=auth_headers) assert response.status_code == 200 assert b"<h2>Upload</h2>" in response.data
步骤3:解决其他API调用错误
socket.gaierror:确认Auth0租户域名拼写正确(如替换为your-tenant.us.auth0.com格式)CannotSendRequest:每次请求后调用conn.close(),或每次请求创建新的连接对象,避免重复使用同一连接
关键注意点
- 单元测试优先用Mock认证,避免依赖外部服务,提升测试稳定性与速度,避免GitHub Actions中因网络或Auth0限流失败
- 路由依赖session用户信息的逻辑,与client credentials机器身份的认证流程不匹配,这是重定向的核心原因
内容的提问来源于stack exchange,提问作者mlsmzk
相关产品推荐
相关产品推荐

