Home > front end >  DRF APITestCase force_authenticate make request.user return tuple instead of User object
DRF APITestCase force_authenticate make request.user return tuple instead of User object

Time:11-25

I have a custom authentication class following the docs

class ExampleAuthentication(authentication.BaseAuthentication):
    def authenticate(self, request):
        username = request.META.get('HTTP_X_USERNAME')
        if not username:
            return None

        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            raise exceptions.AuthenticationFailed('No such user')

        return (user, None)

and I used it in my APIView:

class profile(APIView):
    permission_classes = ()
    authentication_classes = (ExampleAuthentication,)

    def get(self, request, format=None):
        try:
            print('user', request.user)
            serializer = GetUserSerializer(request.user)

            return JsonResponse({'code': 200,'data': serializer.data}, status=200)
        except Exception as e:
            return JsonResponse({'code': 500,'data': "Server error"}, status=500)

when I try to call it normally from the API through postman I got the following result from the print and it worked normally:

user User(143)

I wrote a test using force_authenticate():

class BaseUserAPITest(APITestCase):
    def setUp(self):
      # self.factory = APIRequestFactory()
      self.user = models.User.objects.get_or_create(
                username='test_user_1',
                uid='test_user_1',
                defaults={'agent_type': 1}
            )

    def test_details(self):
      url = reverse("api.profile")
      self.client.force_authenticate(user=self.user)
      response = self.client.get(url)
      self.assertEqual(response.status_code, 200)
  

I got server error because the print of request.user return a tuple instead of a User object, this is the print from the test log

user (<User: User(143)>, True)

I tried searching up and seem like there no result or explanation on why this happening

My version:

django==2.2.8
djangorestframework==3.10.2

CodePudding user response:

The problem is not force_authenticate but get_or_create method. It returns tuple. First element of the tuple is object and second one is boolean indicating if object was created or not. To fix change your code in setUp method to this:

def setUp(self):
      # self.factory = APIRequestFactory()
      self.user, _ = models.User.objects.get_or_create(
                username='test_user_1',
                uid='test_user_1',
                defaults={'agent_type': 1}
            )
  • Related