DRF测试中携带JWT令牌请求接口返回401认证错误排查
DRF JWT授权测试返回401错误定位
你的两段测试代码一共存在3个直接导致认证失败的问题,以及2个会引发后续断言错误的隐患:
- 核心错误1:测试客户端实例不匹配
两段代码都手动实例化了新的APIClient()对象赋值给client变量,并且把认证头设置在了这个新实例上,但实际发送GET请求时调用的是self.client——这是APITestCase类自带的测试客户端实例,从未被设置过任何认证信息,所有请求默认以匿名用户身份发送,自然会返回401未授权。 - 核心错误2:请求头字段名不符合DRF测试客户端规范
第二段代码设置认证头时写的字段名是AUTHORIZATION,DRF测试客户端识别自定义HTTP请求头时,要求必须加HTTP_前缀,正确的字段名是HTTP_AUTHORIZATION,否则框架不会将该字段识别为HTTP请求中的Authorization头,认证信息根本不会被传给后端鉴权逻辑。 - 核心错误3:GET请求参数传递错误
两段代码都把format='json'放在了data参数里传递,DRF测试客户端的get()/post()等方法中,format是方法的独立入参,放在data字典里不会被识别,可能导致请求格式不符合预期。
修正后的参考代码
方案1:直接使用setUp阶段生成的令牌测试
class ImageViewsTests(APITestCase): def setUp(self): self.test_user = User.objects.create_user(**TEST_USER) # 复制全局常量避免测试间数据污染 test_image_data = TEST_IMAGE.copy() test_image_data['created_by'] = self.test_user self.temp_image = Image.objects.create(**test_image_data) self.token = RefreshToken.for_user(self.test_user) def test_images_list(self): # 直接给实际发请求的self.client设置认证头,无需新建APIClient实例 self.client.credentials(HTTP_AUTHORIZATION=f'JWT {self.token.access_token}') response = self.client.get('/image/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) # 注意:列表接口返回的是数组/分页结构,不要直接和单条图片数据比对,按实际返回结构调整断言
方案2:调用登录接口获取令牌测试
def test_images_list(self): login_url = reverse('jwt-create') # 全程使用self.client发送请求,无需新建客户端实例 resp = self.client.post( login_url, {'email':TEST_USER['email'], 'password':TEST_USER['password']}, format='json' ) self.assertEqual(resp.status_code, status.HTTP_200_OK) # 使用正确的HTTP头字段名设置认证信息 self.client.credentials(HTTP_AUTHORIZATION=f'JWT {resp.data["access"]}') response = self.client.get('/image/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK)
额外注意事项
- 不要在测试逻辑中直接修改全局的
TEST_IMAGE常量,多个测试用例串行执行时会出现数据污染,建议每次使用前做一次copy - 如果你的图片列表接口开启了分页,返回结构会是
{"count": 1, "next": null, "previous": null, "results": [图片数据]}格式,直接用response.data和单条TEST_IMAGE做相等断言会失败,需要调整断言逻辑匹配实际返回结构
内容的提问来源于stack exchange,提问作者MattyOstrowsky
相关产品推荐
相关产品推荐

