Magzum Kalybek
Magzum Kalybek

Reputation: 58

How can I use JWT token in DRF tests?

I need to test my API. For example, I have images list page. I need to do tests for this page, but I cannot do this without authentication. I use JWT. I do not know how to do it. Help me please.

tests.py

class ImagesListTestCase(APITestCase):
    def test_images_list(self):
        response = self.client.get('/api/', HTTP_AUTHORIZATION="JWT {}".format("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTkzNzUxMzMxLCJqdGkiOiI3NWE3NDNkMGU3MDQ0MGNiYjQ3NDExNjQ3MTI5NWVjNSIsInVzZXJfaWQiOjF9.7HkhZ1hRV8OtQJMMLEAVwUnJ0yDt8agFadAsJztFb6A"))
        self.assertEqual(response.status_code, status.HTTP_200_OK)

I tried to do

response = self.client.get('/api/', Authorization="Bearer <token>")

Also

response = self.client.get('/api/', Authorization="JWT <token>")

response = self.client.get('/api/', HTTP_AUTHORIZATION="Bearer <token>")

Upvotes: 1

Views: 751

Answers (3)

Yash Agrawal
Yash Agrawal

Reputation: 464

Instead of invoking api to get the token, Another very simple solution can as follows

from rest_framework_simplejwt.tokens import AccessToken

 def setUp(self):
    self.factory = APIRequestFactory() 
    user = User.objects.create_user(
        username='jacob', email='[email protected]', password='top_secret')
    self.client = APIClient()
    token = AccessToken.for_user(user=user)
    self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {token}')

and it will be used as

def test_get_cities(self):
    response = self.client.get('/<actual path to url>/cities/')
    assert response.status_code == 200
    assert len(response.data) == 0
    self.assertEqual(response.data, [])

Important thing to notice here is in setUp function token is generated using AcessToken class from JWT itself, so no actual API is required for testing other flows in your app.

Upvotes: 0

SanRaph
SanRaph

Reputation: 369

You can create users that require JWT authentication like:

    def setUp(self) -> None:
    self.client = APIClient()

    if os.environ.get('GITHUB_WORKFLOW'):
        local_token_url = 'https://testing/app/token/jwt'
    else:
        local_token_url = 'http://127.0.0.1:8000/app/token/jwt'

    response = requests.post(local_token_url, {'email': '[email protected]', 'password': '123pass321'})
    self.test_user1 = json.loads(response.text)
    response = requests.post(local_token_url, {'email': '[email protected]', 'password': '123pass321'})
    self.test_user2 = json.loads(response.text)

    self.contact_person = apm.AppUser.objects.create(email="[email protected]", first_name="John",
                                                     last_name="Doe",
                                                     company_name="test_company_1", phone_number="08077745673",
                                                     is_active=True)

you can then use them like below parsing data = {}

self.client.credentials(HTTP_AUTHORIZATION="Bearer {}".format(self.test_user1.get('access')))
    response = self.client.post(reverse('create-list'), data=data, format='json')
    print(response.data)
    self.assertEqual(response.status_code, status.HTTP_201_CREATE

Upvotes: 0

Younes Moradi
Younes Moradi

Reputation: 162

django creates a temporary database for test; so it's better to get token from username and password like this:

class ImagesListTestCase(APITestCase):
    def setUp(self) :
    self.register_url = reverse("your:register:view")  # for example : "users:register"
    self.user_data = {
        "username": "test_user",
        "email": "[email protected]",
        "password": "123456"
    }
    self.client.post(self.register_url,self.user_data)      # user created

    auth_url = reverse("your:login:view") #for example :"users:token_obtain_pair"
    self.access_token = self.client.post(auth_url,{
        "username" : self.user_data.get("username") ,
        "password" : self.user_data.get("password")
    }).data.get("access")       # get access_token for authorization
    self.client.credentials(HTTP_AUTHORIZATION=f'Bearer {self.access_token}')
    
    def test_images_list(self):
        response = self.client.get('/api/')
        self.assertEqual(response.status_code, status.HTTP_200_OK)

Upvotes: 6

Related Questions