django - 登录测试期间身份验证失败
问题描述
我正在尝试测试自定义登录(使用 pytest),但身份验证失败返回无。这是views.py
from rest_framework.authtoken.views import ObtainAuthToken
from my_auth.api.serializers import UserLoginSerializer
class LoginAuthToken(ObtainAuthToken):
serializer_class = UserLoginSerializer
序列化程序.py
from django.contrib.auth import authenticate
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from rest_framework.authtoken.serializers import AuthTokenSerializer
class UserLoginSerializer(AuthTokenSerializer):
username = None
email = serializers.EmailField(
label=_("Email"),
)
def validate(self, attrs):
email = attrs.get('email')
password = attrs.get('password')
if email and password:
user = authenticate(request=self.context.get('request'),
email=email, password=password) # returns None
if not user:
msg = _('Unable to log in with provided credentials.')
raise serializers.ValidationError(msg, code='authorization') # raises
else:
msg = _('Must include "email" and "password".')
raise serializers.ValidationError(msg, code='authorization')
attrs['user'] = user
return attrs
测试.py
import pytest
from django.urls import reverse
from rest_framework import status
from rest_framework.authtoken.models import Token
from rest_framework.test import APIClient
@pytest.fixture
def test_user():
user = MyUser.objects.create(
email='test@m.com',
first_name='Firstname',
last_name='Lastname'
)
user.set_password('pass5678')
return user
@pytest.mark.django_db
def test_login(test_user):
client = APIClient()
response = client.post(
path=reverse('login'),
data={
'email': 'test@m.com',
'password': 'pass5678',
},
format='json',
)
assert(response.status_code == status.HTTP_200_OK)
token = Token.objects.get(user=test_user)
assert(token.key == response.data['token'])
终端输出:
========================================================================================================== test session starts ==========================================================================================================
platform linux -- Python 3.8.5, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
django: settings: news_project.settings (from ini)
rootdir: /home/andrei/NEWS/news_project, configfile: pytest.ini
plugins: lambda-1.2.4, Faker-8.4.0, common-subject-1.0.5, assert-utils-0.2.2, drf-1.1.2, fixture-order-0.1.3, django-4.3.0
collected 2 items
my_auth/tests.py F [ 50%]
news/tests.py . [100%]
=============================================================================================================== FAILURES ================================================================================================================
______________________________________________________________________________________________________________ test_login _______________________________________________________________________________________________________________
test_user = <MyUser: test@m.com>
@pytest.mark.django_db
def test_login(test_user):
client = APIClient()
response = client.post(
path=reverse('login'),
data={
'email': 'test@m.com',
'password': 'pass5678',
},
format='json',
)
> assert(response.status_code == status.HTTP_200_OK)
E assert 400 == 200
E + where 400 = <Response status_code=400, "application/json">.status_code
E + and 200 = status.HTTP_200_OK
my_auth/tests.py:78: AssertionError
----------------------------------------------------------------------------------------------------------- Captured log call -----------------------------------------------------------------------------------------------------------
WARNING django.request:log.py:224 Bad Request: /api/auth/login/
======================================================================================================== short test summary info ========================================================================================================
FAILED my_auth/tests.py::test_login - assert 400 == 200
====================================================================================================== 1 failed, 1 passed in 3.63s ======================================================================================================
这是我print(response.data)
在 test_login 中执行的输出
{'non_field_errors': [ErrorDetail(string='Unable to log in with provided credentials.', code='authorization')]}
一开始我以为rest_framework.request.Request对象没有传递给UserLoginSerializer的validate(),但实际上是这样。而且,它和我通过 Postman 发送 POST 请求时得到的 Request 几乎是一样的。我错过了什么?
解决方案
调用后您仍然需要调用save
用户set_password
:
@pytest.fixture
def test_user():
user = MyUser.objects.create(
email='test@m.com',
first_name='Firstname',
last_name='Lastname'
)
user.set_password('pass5678')
user.save()
return user
https://docs.djangoproject.com/en/3.2/ref/contrib/auth/#django.contrib.auth.models.User.set_password
将用户的密码设置为给定的原始字符串,注意密码散列。不保存用户对象。
推荐阅读
- r - 从列表列表中删除 NA 并保留 R 中的结构
- go - BigQuery 流式插入在 GKE 上失败
- python - 从预定义的布局将选项卡插入 QTabWidget
- python - 如何在 Python 中检查包含相同短语的相同数据框行?
- c - 生成固定长度的随机字符串(使用C)
- sql - 如何使用更新语句在 oracle sql 的列中连接字符串
- javascript - 在 vscode 调试器中使用 NODE_PATH
- html - 背景图像后未出现元素
- r - 如何在 r 的用户列中制作相同的格式?
- airflow-scheduler - 气流 ssh 操作员错误 cryptography.fernet.InvalidToken