[英]UNIT TEST- Django DRF - How to calling methods in ModelViewSets (Avoid 404 Error)
[英]Django Unit Testing (with DRF): How to test a Passwordresetview?
我目前正在嘗試編寫單元測試以成功重置密碼。
TLDR:我無法弄清楚如何在設置密碼視圖的發布請求中處理表單數據的注入。
對於上下文,讓我先給您我的代碼,因為一行代碼說出1000多個單詞。
賬戶/ API / views.py:
class PasswordResetView(generics.GenericAPIView):
"""(POST) Expects email. Sends a password reset mail to email."""
permission_classes = (permissions.AllowAny,)
serializer_class = PasswordResetSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid(raise_exception=True):
user = User.objects.get(email=serializer.data['email'])
if user.is_active and user.has_usable_password():
send_password_reset_email(user, request)
return Response(
{"detail": "A password reset email has been send."},
status=status.HTTP_204_NO_CONTENT
)
else:
return Response(
{"detail": "This users password can't be reset."},
status=status.HTTP_406_NOT_ACCEPTABLE
)
賬戶/ API / urls.py:
url(r'^password_reset/$', views.PasswordResetView.as_view(),
name="password_reset"),
賬戶/ API / serializers.py:
class PasswordResetSerializer(serializers.Serializer):
email = serializers.EmailField()
def validate_email(self, value):
if User.objects.filter(email__iexact=value).exists():
return value
else:
raise serializers.ValidationError("Email not found.")
賬戶/ utils.py:
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.contrib.sites.shortcuts import get_current_site
from django.utils import six
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
from templated_email import send_templated_mail
password_reset_token = PasswordResetTokenGenerator()
def build_email_context(user_obj, request):
current_site = get_current_site(request)
context = {
"name": "",
"domain": current_site.domain,
"uid": urlsafe_base64_encode(force_bytes(user_obj.pk)),
'token': password_reset_token.make_token(user_obj)
}
if user_obj.name != "":
context["name"]: " " + user_obj.name
return context
def send_password_reset_email(user_obj, request):
context = build_email_context(user_obj, request)
send_templated_mail(
template_name="password_reset",
from_email="noreply@ordersome.com",
recipient_list=[user_obj.email],
context=context
)
鏈接到電子郵件中的路由的視圖是django.contrib.auth中的標准CBV PasswordResetConfirmView和PasswordResetDoneView。
這是我為此密碼重置序列編寫的測試:
API /測試/ test_views.py:
from django.contrib.auth import get_user, get_user_model
from django.core import mail
from rest_framework import status
from rest_framework.authtoken.models import Token
from rest_framework.reverse import reverse as api_reverse
from rest_framework.test import APITestCase
User = get_user_model()
class UserAPIViewsTestCase(APITestCase):
def setUp(self):
User.objects.create_user(
email="testuser@test.com", password="test1234")
self.login_url = api_reverse("api:auth:login")
self.register_url = api_reverse("api:auth:register")
self.password_reset_url = api_reverse("api:auth:password_reset")
self.password_change_url = api_reverse("api:auth:password_change")
self.user_delete_url = api_reverse("api:auth:user_delete")
def test_api_auth_password_reset_success(self):
"""Test if a password reset successfully resets password."""
pre_user = User.objects.get(email="testuser@test.com")
self.assertEqual(pre_user.check_password("test1234"), True)
email_data = {
"email": "testuser@test.com",
}
email_response = self.client.post(
self.password_reset_url, email_data, format="json")
self.assertEqual(email_response.status_code,
status.HTTP_204_NO_CONTENT)
password_reset_data = {
"new_password1": "newtest1234",
"new_password2": "newtest1234"
}
password_reset_response = self.client.get(
mail.outbox[0].body[-94:-37], format="json", follow=True)
path = password_reset_response.request["PATH_INFO"]
done_url = "http://testserver" + path
password_reset_done_response = self.client.post(
done_url, password_reset_data, format="json")
post_user = User.objects.get(email="testuser@test.com")
self.assertEqual(post_user.check_password("newtest1234"), True)
最后一個self.assertEqual
失敗。 但是,當我手動測試視圖時,它可以工作,因此代碼應該正確。 我應該如何修改測試?
當我注銷done_url
它會給我http://testserver/auth/reset/MQ/set-password/
,這應該是正確的路徑。
當我注銷password_reset_done_response
它說,這是TemplateResponse,status_code是200(這應該表示成功,但不是)。 同樣,此響應似乎仍具有路徑/auth/reset/MQ/set-password/
,現在不再是這種情況了。
password_reset_data
不完整-沒有信息將新密碼應用於哪個用戶。
from django.contrib.auth.tokens import default_token_generator
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
...
password_reset_data = {
'uid': urlsafe_base64_encode(force_bytes(pre_user.pk)),
'token': default_token_generator.make_token(pre_user),
'new_password1': 'newtest1234',
'new_password2': 'newtest1234',
}
其他建議
setUp(self)
應該調用super().setUp()
self.assertTrue
而不是self.assertEqual
post_user
,在最后聲明之前使用pre_user.refresh_from_db()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.