DRF+JWT登录功能测试异常求助:无法通过凭证登录
我之前也碰到过一模一样的问题!DRF JWT的登录功能手动跑完全正常,但测试用例死活报凭证错误,折腾了好一阵才捋清楚几个常见的坑,给你挨个排查试试:
测试用户密码未正确哈希:这是最常见的坑!很多人写测试用例时直接给
User模型的password字段设明文,但Django需要通过create_user()方法或者set_password()来生成哈希密码,不然数据库里存的是明文,JWT认证时根本匹配不上。
错误写法:user = User.objects.create(username='admin', password='test123')正确写法二选一:
# 方法1:用create_user自动哈希密码 user = User.objects.create_user(username='admin', password='test123') # 方法2:手动设置并保存哈希密码 user = User.objects.create(username='admin') user.set_password('test123') user.save()请求参数格式不匹配:JWT的默认登录接口(比如
rest_framework_simplejwt的TokenObtainPairView)默认接收application/x-www-form-urlencoded格式的参数,如果你测试时用JSON格式传参,接口可能解析不到用户名和密码。测试时要指定正确的content_type:response = self.client.post( '/api/token/', # 你的JWT登录接口路径 data={'username': 'admin', 'password': 'test123'}, content_type='application/x-www-form-urlencoded' )如果你自定义了视图支持JSON格式,要确保请求头里带
Content-Type: application/json。测试用户状态异常:检查测试用例里创建的用户是否被标记为
is_active=False——手动登录用的是正常激活的用户,但如果是用User.objects.create()手动创建用户(而非create_user),或者自定义用户模型修改了默认状态,就可能导致用户未激活。创建测试用户时最好显式声明:user = User.objects.create_user( username='test_admin', password='test_pass123', is_active=True )自定义认证后端的额外限制:如果项目里自定义了
AuthenticationBackend,比如加了邮箱验证、IP白名单或者其他额外校验逻辑,测试环境可能没满足这些条件。比如后端要求用户必须验证邮箱才能登录,但测试用户没设置email_verified=True,这时候就会认证失败。测试数据库数据污染:有时候测试用例之间没正确隔离,比如前一个测试修改了用户状态但没回滚,导致后续测试用的用户异常。可以检查测试用例是否继承了
TestCase(它会自动在每个测试后回滚数据库),或者在setUp()方法里确保每次都创建全新的测试用户。
给你一个完整的正确测试用例示例:
from django.test import TestCase from django.contrib.auth.models import User from rest_framework.test import APIClient class JWTLoginTestCase(TestCase): def setUp(self): self.client = APIClient() # 创建符合要求的测试用户 self.test_user = User.objects.create_user( username='test_admin', password='secure_test_pass_123', is_active=True ) def test_successful_jwt_login(self): # 发送正确格式的登录请求 response = self.client.post( '/api/token/', data={ 'username': self.test_user.username, 'password': 'secure_test_pass_123' }, content_type='application/x-www-form-urlencoded' ) # 断言登录成功,返回token self.assertEqual(response.status_code, 200) self.assertIn('access', response.data) self.assertIn('refresh', response.data)
如果以上方法都没解决问题,可以把你的测试用例代码、登录视图代码或者自定义认证后端的代码贴出来,这样更容易精准定位问题!
内容的提问来源于stack exchange,提问作者niedzwiedzwo

