What is the correct way to test tokens based on APIRequestFactory?

The request to my endpoint works fine (as long as I give it a valid token), it returns a json representation of my response data.

The code in the api service that calls my endpoint by passing the auth token in the header:

headers = {'content-type': 'application/json', 'Authorization': 'Token {}'.format(myToken)} url = 'http://localhost:8000/my_endpoint/' r = session.get(url=url, params=params, headers=headers) 

In views.py, I have a method decorator that wraps the submit method in the view (viewsets.ReadOnlyModelViewSet):

 def login_required(f): def check_login_and_call(request, *args, **kwargs): authentication = request.META.get('HTTP_AUTHORIZATION', b'') if isinstance(authentication, str): authentication = authentication.encode(HTTP_HEADER_ENCODING) key = authentication.split() if not key or len(key) != 2: raise PermissionDenied('Authentication failed.') user, token = authenticate_credentials(key[1]) return f(request, *args, **kwargs) return check_login_and_call 

I am trying to write a test to authenticate a request with a token:

 from rest_framework.authtoken.models import Token from rest_framework.test import APIRequestFactory from rest_framework.test import APITestCase from rest_framework.test import force_authenticate class EndpointViewTest(APITestCase): def setUp(self): self.factory = APIRequestFactory() self.user = User.objects.create_user( username=' user@foo.com ', email=' user@foo.com ', password='top_secret') self.token = Token.objects.create(user=self.user) self.token.save() def test_token_auth(self): request = self.factory.get('/my_endpoint') force_authenticate(request, token=self.token.key) view = views.EndpointViewSet.as_view({'get': 'list'}) response = view(request) self.assertEqual(response.status_code, 200) json_response = json.loads(response.render().content)['results'] 

For some reason, I cannot get the request to pass the token correctly for this test. Using force_authenticate does not seem to change the header that I use to validate the token. The current output raises "PermissionDenied: Authentication Error". because the token is not set in the request.

Is there a way to set this in the request header in my test or reorganize the way I use it first?

+5
source share
2 answers

I found a way to pass the test, but please write if you have a better idea of ​​how to handle this.

 request = self.factory.get('/my_endpoint', HTTP_AUTHORIZATION='Token {}'.format(self.token)) force_authenticate(request, user=self.user) 

After changing the above two lines of the test, it seems to authenticate correctly based on the token.

+11
source

Sorry for digging this old thread, but if someone uses APIClient() to run their tests, you can do the following:

 from rest_framework.test import APITestCase from rest_framework.test import APIClient from rest_framework.authtoken.models import Token from django.contrib.auth.models import User class VehicleCreationTests(APITestCase): def setUp(self): self.client = APIClient() self.user = User.objects.create_superuser('admin', ' admin@admin.com ', 'admin123') self.token = Token.objects.create(user=self.user) def testcase(self): self.client.force_login(user=self.user) response = self.client.post('/api/vehicles/', data=vehicle_data, format='json', HTTP_AUTHORIZATION=self.token) self.assertEqual(response.status_code, 201) 

A really good resource that I used to come up with is the django-rest-framework -jwt tests

+2
source

Source: https://habr.com/ru/post/1201262/


All Articles