0

I've checked the DRF official documentation, have read the below posts and copy-pasted code from some answers to avoid any typo, but I still can't authenticate in my unit tests. I always get a 401 response code.

I have a custom User model that just has a couple of none required fields so far.

Can anyone see any logic issue, or error in the code? Could the issue originate from having a proper local DB and a testing DB and the authentication mixing both up somehow?

I've had to use self.client.force_authenticate(user=self.user, token=None) to bypass the authentication issue. But that defeats the purpose of the tests.

Checked posts that did not solve the problem:

So here's my code.

Unit test

from django.test.testcases import SimpleTestCase
from django.urls import reverse, resolve
from rest_framework import status
from rest_framework.test import APITestCase
from rest_framework.authtoken.models import Token
from test_project.models.user import *
from test_project.views import UserViewSet
# from django.contrib.auth.models import User
from test_project.models import *


class UserAPIViewTests(APITestCase):

  def setUp(self) -> None:
    self.users_list_url = reverse('user-list')
    self.users_detail_url = reverse('user-detail', args=[1])
    self.user =User.objects.create(
      username="admin",
      password="admin",
      email="test@necktie.com",
      first_name="test first name",
      last_name="test last name",
      is_superuser=True,
      is_staff=True,
      is_active=True
    )
    self.token = Token.objects.create(user=user)
    self.client.credentials(HTTP_AUTHORIZATION='Bearer ' + self.token.key)

  # The testing DB is automatically torn down, no implementation required for those tests
  def tearDown(self) -> None:
    pass


  def test_get_users_authenticated(self):
    """
    Test that an authenticated user can get the users' list
    """
    response = self.client.get(self.users_list_url)
    self.assertEquals(response.status_code, status.HTTP_200_OK)

User model

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import gettext_lazy as _

class User(AbstractUser):
  """auth/login-related fields"""
  gender = models.CharField(_('gender'), max_length=50, null=True)
  nationality = models.CharField(_('nationality'), max_length=50, null=True)


  def __str__(self):
    return "{} {}".format(self.first_name, self.last_name)

User View

from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import permissions
from ..models.user import User
from ..serializers.user import *
from ..permissions import *

class UserViewSet(viewsets.ModelViewSet):
  """
  This viewset automatically provides `list`, `create`, `retrieve`,
  `update` and `destroy` actions.
  """
  queryset = User.objects.all()
  serializer_class = UserSerializer

  def get_permissions(self):
    """
    Method to apply permissions depending on request type (GET, PUT etc.)
    """
    if self.request.method == 'GET':
      return [permissions.IsAuthenticated(), IsStaff()]
    else:
      return [permissions.IsAuthenticated(), IsSuperuser()]

User serializers

from rest_framework import serializers
from ..models.user import User


class UserSerializer(serializers.ModelSerializer):
  """
  Serializer for all actions on User model
  """

  class Meta:
    model = User
    fields = [
      'id',
      'username',
      'first_name',
      'last_name',
      'is_staff',
      'is_superuser',
      'is_active',
      'date_joined'
    ]

Thanks for the help!

Seb
  • 363
  • 1
  • 18
  • Have you tried using `Token` instead of `Bearer`? – Brian Destura Oct 14 '21 at 02:08
  • Yes I have. Have tried both as the documentation indicates ```Token``` but my authentication process requires a ```Bearer``` token. Neither work, always get a 401 response even though the user instance is created and has proper roles. – Seb Oct 15 '21 at 03:42

0 Answers0