[drf | endpoint] Build a Backend REST API - 27

Hyeseong·2021년 3월 5일
0

Add tests for manage user endpoint 🤓

manage user endpoint를 작성해보도록 할게요.

  • 역할 : 인증된 유저만 profile 수정을 가능하게함.(이름,이메일,비밀번호 변경)

step1 - test

test_retrieve_user_unauthorized 😈

test_user_api로 갈게요.

ME_URL을 지정할게요. 그리고 test_retrieve_user_unauthorized 메서드를 작성합니다.

테스트의 목적은 로그인하지 않은(토큰 발급X)유저가 접근이 불가한 엔드포인트에 갔을시 이에 대응하는 테스트 반응을 도출하기 위해서에요.

...
...
ME_URL = reverse('user:me') # 테스트할 url을 등록

class PublicUserApiTests(TestCase):
    """Test the users API (public)"""
	...
    ...
    ...
    # 가장 'PublicUserApiTests'의 아래에 추가할게요.
    def test_retrieve_user_unauthorized(self):
        """Test that authentication is required for users"""
        res = self.client.get(ME_URL)
        
        self.assertEqual(res.status_code, status.HTTP_401_UNAUTHORIZED)

test_retrieve_profile_success 🤡

새로운 클래스, PublicUserApiTests를 만들게요.
또한 setUp 메서드를 정의해서 테스트 하기전 밑작업으로 매번 사용할 아이디, 이름, 비밀번호를 하드타이핑하지 않게 만들구~

APIClient객체를 클래스의 인스턴스 속성에 넣구
또한 이번 테스트는 인증이 되었다는 전제하에서 모든 테스트가 진행되어야 하기 때문에
force_authenticate 역시 작성하도록 할게요.

참고로 force_authenticate은 인증이 필요한 요청일 때 강제로 자격을 부여하는 함수에요. 권한이 필요한 테스트일 때 사용하고요

from rest_framework.test import force_authenticate

force_authenticate(request, user=None, token=None)

사용자, 토큰 둘 중 하나 혹은 둘 다를 설정해 해당 request를 인증해요.

아래와 같이 일단 PrivateUserApiTests클래스에 대한 작성을 할게요.

...
...
...

    def test_retrieve_user_unauthorized(self):
        """Test that authentication is required for users"""
        res = self.client.get(ME_URL)
        
        self.assertEqual(res.status_code, status.HTTP_401_UNAUTHORIZED)

class PrivateUserApiTests(TestCase):
    """Test API requires that require authentication"""
    
    def setUp(self):
        self.user = create_user(
            email='test@test.com',
            password='testpass',
            name='name',
        )
        self.client = APIClient()
        self.client.force_authenticate(user=self.user)
        
    # Test retrieving profile for logged in user
    # Also test if the response contain the expected data
    def test_retrieve_profile_success(self):
        """Test retrieving profile for logged in used"""
        res = self.client.get(ME_URL)
        self.assertEqual(res.status_code, status.HTTP_200_OK)
        self.assertEqual(res.data, {
            'name': self.user.name,
            'email': self.user.email,
        })

test_retrieve_profile_success 유저 프로파일 GET요청시 테스트인데요. 이름과 이메일 정보가 나타나야겠조?!

test_post_me_not_allowed 👹

post요청을 할텐데. 이경우 등록된 유저의 정보를 post() 메서드의 2 번째 인자로 입력하지 않을시 405오류를 반환하도록 하는거에요.

    # Test if post if not allowed in to this api
    def test_post_me_not_allowed(self):
        """Test that POST is not allowed on the me url"""
        res = self.client.post(ME_URL, {})

        self.assertEqual(res.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)

tet_update_user_profile 👺

마지막 post요청은 test_post_me_not_allowed 테스트와 다르게 payload를 post() 메서드에 넣어서 확인하게 되요.

새로 보이는 refresh_from_db() 가 있는데요. 설명은 짧게 아래와 같아요.

모델 객체를 데이터베이스에서 다시 읽어들일때 사용
refresh_from_db() 메서드를 사용하여 데이터베이스에서 모델을 다시 읽어들일 수 있습니다. 값을 갱신하는 테스트를 작성할 때 유용합니다.

post()요청으로 DB에 변화를 즉각적으로 줬지만 남은 assertEqual(), assertTrue() 테스트를 해야하기에 필요해요.

깜빡 할 수 있을텐데 check_password 다시 한번 확인하는 시간 가질게요.

check_password(raw_password)¶
Returns True if the given raw string is the correct password for the user. (This takes care of the password hashing in making the comparison.)

그러면 아래와 같이 인증한 유저에 대한 테스트 코드가 마무리 됩니다.

    # test update user profile
    def tet_update_user_profile(self):
        """Test updating the user profile for authenticated user"""
        payload = {"name": "new name", "password":'newpassword123'}
        res = self.client.patch(ME_URL, payload)
        
        self.user.refresh_from_db()
        self.assertEqual(self.user.name, payload['name'])
        self.assertTrue(self.user.check_password(payload['password']))
        self.assertEqual(res.status_code, status.HTTP_200_OK)

그럼 test를 돌려보면 아래와 같이 콘솔에 찍힐 거에요.

Reverse for 'me' not found. 'me' is not a valid view function or pattern name.

profile
어제보다 오늘 그리고 오늘 보다 내일...

0개의 댓글