Django tests.py中如何为已认证用户发送带Token认证的POST请求?
问题核心原因
- 用户创建逻辑错误:直接使用
User.objects.create存储明文密码,未经过Django认证体系要求的哈希加密,所有密码校验都会失败 - 认证逻辑不匹配:你使用DRF的Token认证,而Django原生测试客户端的
login()/force_login()仅适配Session认证,Token认证不会读取session中的用户信息,所以即使确认session内有登录记录,接口依然返回403 - 获取Token的参数错误:请求
/api-token-auth时传入的self.user1.password是数据库存储的哈希后的值,不是原始明文密码,自然校验失败 - 响应打印逻辑错误:DRF返回的
Response对象没有context属性,所以打印结果为None,查看响应内容应该用response.json()或response.content
修复步骤
第一步:修复用户创建逻辑
改用create_user方法,Django会自动对密码做哈希处理,同时提前为测试用户生成Token:
class TodoTests(TestCase): @classmethod def setUpTestData(cls): # 改用create_user自动加密密码 cls.user1 = User.objects.create_user( username="xxxxx", email="xxxxx@gmail.com", password="password123", ) # 手动为用户生成DRF Token(如果没有配置全局自动生成Token的信号,这一步必须加) from rest_framework.authtoken.models import Token cls.user1_token = Token.objects.create(user=cls.user1)
第二步:选择适配Token认证的测试方案
方案1:模拟真实请求携带Token头(最贴近实际使用场景)
def test_post_new_task_authorized_user(self): data = { "title": "A new post", "description": "Description of post", "responsible_username": "xxxxx", } # 请求头加入Token认证信息 response = self.client.post( reverse("CUDtasks"), data, content_type="application/json", HTTP_AUTHORIZATION=f"Token {self.user1_token.key}" ) # 打印响应内容用json() print("响应内容:", response.json()) self.assertEqual(response.status_code, 200)
方案2:使用DRF专属测试客户端简化流程(单元测试更高效)
直接用force_authenticate绕过认证流程,不需要处理Token:
# 导入DRF的测试客户端 from rest_framework.test import APIClient class TodoTests(TestCase): @classmethod def setUpTestData(cls): # 这里和上面的修复后的用户创建逻辑一致 cls.user1 = User.objects.create_user( username="xxxxx", email="xxxxx@gmail.com", password="password123", ) def setUp(self): # 替换原生Client为APIClient self.client = APIClient() # 直接强制认证当前用户 self.client.force_authenticate(user=self.user1) def test_post_new_task_authorized_user(self): data = { "title": "A new post", "description": "Description of post", "responsible_username": "xxxxx", } # format参数自动处理json编码,不需要手动指定content_type response = self.client.post(reverse("CUDtasks"), data, format="json") self.assertEqual(response.status_code, 200)
可选:修复获取Token的测试逻辑
如果需要测试Token获取接口,把传入的密码改为原始明文即可:
response = self.client.post( "/api-token-auth", {"username": self.user1.username, "password": "password123"}, # 传入明文密码 content_type="application/json", ) print(f"返回的Token: {response.json()}") self.assertEqual(response.status_code, 200)
内容的提问来源于stack exchange,提问作者Jhnsbrst
相关产品推荐
相关产品推荐

