영혼의 소셜로그인 데코레이터unittest

Pang·2021년 10월 31일
0
post-thumbnail

social_login decorator unittest

import json
import jwt

from django.test         import TestCase, Client
from django.db           import transaction

from my_settings         import SECRET_KEY, ALGORITHM
from reservations.models import Reservation, Airline, Airport
from users.models        import User

class TestCase(TestCase):
    @transaction.atomic
    def setUp(self):
        User.objects.bulk_create([
            User(
                id            = 1,
                name          = "현우",
                email         = "msm@naver.com",
                kakao_id      = "1",
                point         = "500000",
                profile_image = "profile1.jpg"
            ),
            User(
                id            = 2,
                name          = "현순",
                email         = "smsm@naver.com",
                kakao_id      = "2",
                point         = "50000000",
                profile_image = "profile2.jpg"
            )
            ])

        self.token = jwt.encode({'id':User.objects.get(kakao_id="1").id}, SECRET_KEY, algorithm=ALGORITHM)
        self.token2 = jwt.encode({'id':User.objects.get(kakao_id="1").id}, SECRET_KEY, algorithm=ALGORITHM)

        Airport.objects.bulk_create([
            Airport(
                id       = 1,
                name     = "김포",
                eng_name = "KMP"
            ),
            Airport(
                id       = 2,
                name     = "제주",
                eng_name = "JEJU"
            )
        ])

        Airline.objects.bulk_create([
            Airline(
                id       = 1,
                name     = "위코드항공",
                eng_name = "wecode",
                logo_url = "we_url"
            ),
            Airline(
                id       = 2,
                name     = "니코드항공",
                eng_name = "necode",
                logo_url = "ne_url"
            )
        ])

        Reservation.objects.bulk_create([
            Reservation(
                id                = 1,
                flight_code       = "we123",
                depart_time       = "10:20",
                arrive_time       = "12:20",
                start_date        = "2021-11-03",
                end_date          = "2021-11-03",
                remain_seats      = 30,
                seat_class        = "일반",
                airline_id        = 1,
                airport_arrive_id = 2,
                airport_depart_id = 1,
                flight_price      = 10000
            ),
            Reservation(
                id                = 2,
                flight_code       = "ne123",
                depart_time       = "11:20",
                arrive_time       = "13:20",
                start_date        = "2021-11-04",
                end_date          = "2021-11-04",
                remain_seats      = 40,
                seat_class        = "비지니스",
                airline_id        = 2,
                airport_arrive_id = 1,
                airport_depart_id = 2,
                flight_price      = 20000
            ),
            Reservation(
                id                = 3,
                flight_code       = "ne123",
                depart_time       = "11:20",
                arrive_time       = "13:20",
                start_date        = "2021-11-04",
                end_date          = "2021-11-04",
                remain_seats      = 40,
                seat_class        = "비지니스",
                airline_id        = 2,
                airport_arrive_id = 1,
                airport_depart_id = 2,
                flight_price      = 6000000
            ),
            Reservation(
                id                = 4,
                flight_code       = "ne123",
                depart_time       = "11:20",
                arrive_time       = "13:20",
                start_date        = "2021-11-04",
                end_date          = "2021-11-04",
                remain_seats      = 0,
                seat_class        = "비지니스",
                airline_id        = 2,
                airport_arrive_id = 1,
                airport_depart_id = 2,
                flight_price      = 600
            )
        ])

    def tearDown(self):
        User.objects.all().delete()
        Airport.objects.all().delete()
        Airline.objects.all().delete()
        Reservation.objects.all().delete()

    def test_success_get_reservation_info(self):
        client       = Client()
        header       = {'HTTP_Authorization' : self.token}
        response     = client.get('/payments/payment?depa-air=1&arri-air=2', content_type='application/json', **header)
        access_token = jwt.decode(self.token, SECRET_KEY, algorithms=ALGORITHM)
        user         = User.objects.get(id = access_token['id'])
        self.assertEqual(response.json(),
        {
            "user_info": {
                "name"  : user.name,
                "email" : user.email
            },
            "depature_airplane_info": {
                "departure_airport"     : "김포",
                "departure_airport_eng" : "KMP",
                "departure_time"        : "10:20:00",
                "arrival_airport"       : "제주",
                "arrival_airport_eng"   : "JEJU",
                "arrival_time"          : "12:20:00",
                "depa_airline_name"     : "위코드항공",
                "depa_airline_logo"     : "we_url",
                "airplane_code"         : "we123",
                "seat_class"            : "일반",
                "price"                 : 10000,
                "start_date"            : "2021-11-03",
                "remain_seats"          : 30,
                "flight_duration"       : "2:00:00"
            },
            
            "arrival_airplane_info": {
                "departure_airport"     : "제주",
                "departure_airport_eng" : "JEJU",
                "departure_time"        : "11:20:00",
                "arrival_airport"       : "김포",
                "arrival_airport_eng"   : "KMP",
                "arrival_time"          : "13:20:00",
                "depa_airline_name"     : "니코드항공",
                "depa_airline_logo"     : "ne_url",
                "airplane_code"         : "ne123",
                "seat_class"            : "비지니스",
                "price"                 : 20000,
                "start_date"            : "2021-11-04",
                "remain_seats"          : 40,
                "flight_duration"       : "2:00:00"
            },
            "total_price": {
                "total_price": 30000
            }
        }
        )

        self.assertEquals(response.status_code, 200)
    
    def test_success_create_passenger(self):
        client       = Client()
        header       = {'HTTP_Authorization' : self.token}
        data     = {
            "first_name"    : 'first_name',
            "last_name"     : 'last_name',
            "nationality"   : 'nationality',
            "birth"         : '2010-10-11',
            "gender"        : 'True'
        }
        response = client.post('/payments/payment?depa-air=1&arri-air=2', json.dumps(data), content_type='application/json', **header)

        self.assertEqual(response.json(),
        {
                "message":"CREATED!"
        })
        
        self.assertEquals(response.status_code,201)
    
    def test_fail_create_passenger_keterror(self):
        client       = Client()
        header       = {'HTTP_Authorization' : self.token}
        data     = {
            "first_name"    : 'first_name',
            "last_ame"      : 'last_name',
            "nationality"   : 'nationality',
            "birth"         : '2010-10-11',
            "gender"        : 'True'
        }
        response = client.post('/payments/payment?depa-air=1&arri-air=2', json.dumps(data), content_type='application/json', **header)

        self.assertEqual(response.json(),
        {
                "message":"KEYERROR"
        })

    def test_fail_payment_not_enough_money(self):
        client       = Client()
        header       = {'HTTP_Authorization' : self.token}
        data     = {
            "first_name"    : 'first_name',
            "last_name"     : 'last_name',
            "nationality"   : 'nationality',
            "birth"         : '2010-10-11',
            "gender"        : 'True'
        }
        response = client.post('/payments/payment?depa-air=1&arri-air=3', json.dumps(data), content_type='application/json', **header)

        self.assertEqual(response.json(),
        {
            "message":"NOT ENOUGH POINTS"
        })
    
    def test_fail_payment_not_enough_seats(self):
        client       = Client()
        header       = {'HTTP_Authorization' : self.token2}
        
        data     = {
            "first_name"    : 'first_name',
            "last_name"     : 'last_name',
            "nationality"   : 'nationality',
            "birth"         : '2010-10-11',
            "gender"        : 'True'
        }
        response = client.post('/payments/payment?depa-air=1&arri-air=4', json.dumps(data), content_type='application/json', **header)

        self.assertEqual(response.json(),
        {
            "message":"THE SEATS ARE SOLD OUT"
        })

간단한 유닛테스트를 진행하였다.

유닛테스트 코드가 직접 쓴 코드의 몇 배는 길었다...

멘토님이 유닛테스트의 중요성을 계속 말해주셔서 마지막에는 조금 열심히 해보았다.

  1. 테이블은 여러 개 만들수록 좋다.
  2. 모든 상황과 예외처리를 생각하면서 유닛테스트를 해라

멘토님에게 엄청 들은 말이다 게다가 유닛테스트 할 때 도 컨벤션을 맞추면서 해야한다니...

혼란

카카오톡 소셜 로그인도 직접 구현하였고 소셜 로그인 유닛테스트까지 이미 마친 상태라
로그인 데코레이터는 별 거 없을 줄 알았다...

 self.token = jwt.encode({'id':User.objects.get(kakao_id="1").id}, SECRET_KEY, algorithm=ALGORITHM)

하지만.. 여기서도 jwt를 이용하여 가상의 토큰을 새로 만들어야만 테스트가 진행되었다.

그리고 이 부분에서 1시간 넘게 고민하다가 내 실수를 찾았다.
처음에는 저렇게 위에처럼 코드를 짜지 않고

get(id=1)이런 식으로 아이디 값을 가져왔다.

그러니까 테스트를 계속 돌려보았지만.
내가 데코레이터에서 예외처리 해둔 유저가 존재하지 않습니다라는 에러만 계속 뜰뿐이었다.

한참을 고민하다가 이게 일반적인 로그인이 아니라 소셜로그인이라는 것을 깨달았고
데코레이터에서 무언가 잘못됐는지 한참 찾았다.

데코레이터를 보니

            access_token = jwt.decode(request.headers.get('Authorization'), SECRET_KEY, algorithms=ALGORITHM)
           user         = User.objects.get(kakao_id = access_token['id'])
           request.user = user

이런... 내가 에초에 kakao_id를 고유값으로 보고 토큰 유효성 검사를 했던 것이었다.

실수를 깨닫고 금방 고쳤다

조금 허무했지만 그래도 내가 쓴 코드조차 내가 잘 이해하고 있지 못했다는 사실에 충격먹었고

결국은 내가 해결했다는 것에 뿌듯함을 느꼈다!!

profile
팡 화이토

0개의 댓글