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!