I am using DRF with the JWT package for authentication. Now, I’m trying to write a unit test that authenticates itself with a JWT token. No matter how I try it, I can’t get the test API client to authenticate itself via JWT. If I do the same with an API client (in my case, Postman), everything works.
This is the test case:
from django.urls import reverse from rest_framework.test import APITestCase from rest_framework_jwt.settings import api_settings from backend.factories import member_factory jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER class MemberTests(APITestCase): def test_get_member(self): member = member_factory() payload = jwt_payload_handler(member.user) token = jwt_encode_handler(payload) self.client.credentials(Authorization='JWT {0}'.format(token)) response = self.client.get(reverse('member-detail', kwargs={'pk': member.pk})) assert response.status_code == 200
But I always get a 401 Authentication credentials were not provided
.
In response.request
I see the token is there, it’s just not being applied I guess.
If I rewrite the test to use rest_framework.test.RequestsClient
and actually send it to the live_server URL, it works.
Any help on this?
P.S.: I am aware of force_authenticate()
and login, but I would like my unit tests to access the API the same as the API client will in production.
Advertisement
Answer
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)