2023-07-06 TIL

0v0baek·2023년 7월 6일
0

TIL

목록 보기
91/92

[drf] 이메일 관련 테스트 코드 작성

이메일 인증과 비밀번호 초기화 관련 테스트 코드를 작성해봤다.
이것저것 import해와서 쓰는게 많아서 좀 버벅였다...

🔎 전체 코드

from django.urls import reverse
from django.core import mail
from django.utils.http import urlsafe_base64_encode
from django.utils.encoding import force_bytes
from rest_framework.test import APITestCase
from users.models import User, UserInfo
from .customtoken import user_email_verify_token

class UserBaseTestCase(APITestCase):
    @classmethod
    def setUpTestData(cls) -> None:
        cls.user_signup_data = {
            "username": "signupuser",
            "password": "qhdks111!",
            "email": "signupuser@gmail.com",
        }
        cls.set_up_user = User.objects.create_user(
            email="testuser@gmail.com",
            password="qhdks111!",
        )
        cls.set_up_userinfo = UserInfo.objects.create(player=cls.set_up_user)
        cls.password_reset_data = {"email": "testuser@gmail.com"}
        cls.user_edit_data = {"username": "testuser"}
        cls.user_login_data = {"email": "testuser@gmail.com", "password": "qhdks111!"}

    def setUp(self) -> None:
        login_user = self.client.post(reverse("login"), self.user_login_data).data
        self.access = login_user["access"]
        self.refresh = login_user["refresh"]
        self.token = user_email_verify_token.make_token(self.set_up_user)
        self.uidb64 = urlsafe_base64_encode(force_bytes(self.set_up_user.pk))

class UserSignUpTestCase(UserBaseTestCase):
    def test_signup(self):
        url = reverse("signup")
        data = self.user_signup_data
        response = self.client.post(
            path=url,
            data=data,
        )
        self.assertEqual(response.status_code, 201)
        self.assertEqual(response.data, {"message": "유저 인증 이메일을 전송했습니다."})
        user = User.objects.get(email=data["email"])
        self.assertTrue(user)

        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(mail.outbox[0].to, [user.email])
        self.assertEqual(mail.outbox[0].subject, f"<한> {user.username}님의 계정 인증")


class UserEmailTestCase(UserBaseTestCase):
    def test_email_verify(self):
        url = reverse(
            "email_verify_view", kwargs={"uidb64": self.uidb64, "token": self.token}
        )
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        # 바뀐 적용사항 확인을 위해 DB refresh 해주기
        self.set_up_user.refresh_from_db()
        self.assertTrue(self.set_up_user.is_active)

    def test_password_reset(self):
        reset_response = self.client.put(
            path=reverse("password_reset_view"),
            data=self.password_reset_data,
        )
        self.assertEqual(reset_response.status_code, 200)

        reset_password = mail.outbox[0].body.split(" ")[4][:6]
        self.password_reset_data["password"] = reset_password

        login_response = self.client.post(reverse("login"), self.password_reset_data)
        self.assertEqual(login_response.status_code, 200)

🔧 회원가입 테스트 코드 리팩토링

class UserSignUpTestCase(UserBaseTestCase):
    def test_signup(self):
        ...
        user = User.objects.get(email=data["email"])
        ...

        self.assertEqual(len(mail.outbox), 1)
        self.assertEqual(mail.outbox[0].to, [user.email])
        self.assertEqual(mail.outbox[0].subject, f"<한> {user.username}님의 계정 인증")

회원가입 이후 추가 인증이 필요없던 기존의 코드와 다르게,

이메일 인증의 경우
이메일이 잘 전송됐는지, 받는 이메일 주소가 올바른지, 제목은 제대로 갔는지를 확인해줘야 한다.

확인을 위해 django.core에서 mailimport해온다.
우리는 .send() 메소드를 실행했을 때 저장되는 Django의 내장 메일 메시지를 보관하는 리스트 outbox를 사용해 줄 것이다.

메일이 잘 전송됐는지 길이를 체크해준다.
그러고 받는 이메일 주소가 맞는지와 제목을 체크해준다.

🔧 이메일 인증 테스트 코드

class UserEmailTestCase(UserBaseTestCase):
    def test_email_verify(self):
        url = reverse(
            "email_verify_view", kwargs={"uidb64": self.uidb64, "token": self.token}
        )
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)
        self.set_up_user.refresh_from_db()
        self.assertTrue(self.set_up_user.is_active)

먼저 setUp에서 저장해준 uidb64token 값을 들고온 뒤, reverse 메소드를 통해 url 주소를 지정해준다.

그런 뒤 요청을 보내고, status code가 올바른지 확인한다.

refresh_from_db()로 DB 상태를 refresh해준 뒤
assertTrueis_active가 변경되었는지 확인해준다.

🔧 비밀번호 초기화 테스트 코드

class UserEmailTestCase(UserBaseTestCase):
    def test_password_reset(self):
        reset_response = self.client.put(
            path=reverse("password_reset_view"),
            data=self.password_reset_data,
        )
        self.assertEqual(reset_response.status_code, 200)

        reset_password = mail.outbox[0].body.split(" ")[4][:6]
        self.password_reset_data["password"] = reset_password

        login_response = self.client.post(reverse("login"), self.password_reset_data)
        self.assertEqual(login_response.status_code, 200)

먼저, put요청으로 비밀번호를 초기화 시켜주고 status code를 확인한다.

그런 뒤, outbox에서 메일을 찾아 본문의 비밀번호 부분만 쪼갠다.
그리고, 그 비밀번호로 다시 login post 요청을 보내 잘 로그인이 되는지 확인해준다.

profile
개발 공부 하는 비전공자 새내기. 꾸준히 합시다!

0개의 댓글