Django Rest Framework JWT Unit Test Django Rest Framework JWT Unit Test python python

Django Rest Framework JWT Unit Test


Try setting up a new APIClient for this test. This is how my own test looks like

 def test_api_jwt(self):    url = reverse('api-jwt-auth')    u = user_model.objects.create_user(username='user', email='user@foo.com', password='pass')    u.is_active = False    u.save()    resp = self.client.post(url, {'email':'user@foo.com', 'password':'pass'}, format='json')    self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)    u.is_active = True    u.save()    resp = self.client.post(url, {'username':'user@foo.com', 'password':'pass'}, format='json')    self.assertEqual(resp.status_code, status.HTTP_200_OK)    self.assertTrue('token' in resp.data)    token = resp.data['token']    #print(token)    verification_url = reverse('api-jwt-verify')    resp = self.client.post(verification_url, {'token': token}, format='json')    self.assertEqual(resp.status_code, status.HTTP_200_OK)    resp = self.client.post(verification_url, {'token': 'abc'}, format='json')    self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)    client = APIClient()    client.credentials(HTTP_AUTHORIZATION='JWT ' + 'abc')    resp = client.get('/api/v1/account/', data={'format': 'json'})    self.assertEqual(resp.status_code, status.HTTP_401_UNAUTHORIZED)    client.credentials(HTTP_AUTHORIZATION='JWT ' + token)    resp = client.get('/api/v1/account/', data={'format': 'json'})    self.assertEqual(resp.status_code, status.HTTP_200_OK)


The following answer applies if you are using Simple JWT and pytest, and Python 3.6+. You need to create a fixture, I have called it api_client, and you need to get the token for an existing user.

from django.contrib.auth.models import Userfrom rest_framework.test import APIClientfrom rest_framework_simplejwt.tokens import RefreshTokenimport pytest@pytest.fixturedef api_client():    user = User.objects.create_user(username='john', email='js@js.com', password='js.sj')    client = APIClient()    refresh = RefreshToken.for_user(user)    client.credentials(HTTP_AUTHORIZATION=f'Bearer {refresh.access_token}')    return client

Notice that in the fixture above, the user is created there, but you can use another fixture to create the user and pass it to this one. The key element is the following line:

refresh = RefreshToken.for_user(user)

This line allows you to create tokens manually as explained in the docs. Once you have that token, you can use the method credentials in order to set headers that will then be included on all subsequent requests by the test client. Notice that refresh.access_token contains the access token.

This fixture has to be used in your tests that you require the user to be authenticated as in the following example:

@pytest.mark.django_dbdef test_name_of_your_test(api_client):    # Add your logic here    url = reverse('your-url')    response = api_client.get(url)    data = response.data    assert response.status_code == HTTP_200_OK    # your asserts


I had similar issue, enclosed I send you my solution just to have more code to compare (tests.py).

from django.urls import reversefrom rest_framework import statusfrom rest_framework.test import APITestCasefrom django.contrib.auth.models import Userclass AuthViewsTests(APITestCase):    def setUp(self):        self.username = 'usuario'        self.password = 'contrasegna'        self.data = {            'username': self.username,            'password': self.password        }    def test_current_user(self):        # URL using path name        url = reverse('tokenAuth')        # Create a user is a workaround in order to authentication works        user = User.objects.create_user(username='usuario', email='usuario@mail.com', password='contrasegna')        self.assertEqual(user.is_active, 1, 'Active User')        # First post to get token        response = self.client.post(url, self.data, format='json')        self.assertEqual(response.status_code, status.HTTP_200_OK, response.content)        token = response.data['token']        # Next post/get's will require the token to connect        self.client.credentials(HTTP_AUTHORIZATION='JWT {0}'.format(token))        response = self.client.get(reverse('currentUser'), data={'format': 'json'})        self.assertEqual(response.status_code, status.HTTP_200_OK, response.content)