3

I have looked at two answers on SO that may already have my answer but frankly I just don't understand them. These SO post are: Django Rest Framework API Authentication Test and Django authenticate unit test.

Both of the SO questions use different approaches.

The approach I am attempting to use is this. I have created this class:

from rest_framework.test import APIClient
from django.test import testcases
from django.contrib.auth.models import User

class RemoteAuthenticatedTest(testcases.TestCase):
    client_class = APIClient

    def setUp(self):
        self.username = 'mister_neutron'
        self.user = User.objects.create_user(username='mister_neutron',
                                          email='[email protected]',
                                             password='F4kePaSs0d')
        super(RemoteAuthenticatedTest, self).setUp()

My unit test looks like this:

class InfoViewTestCase(RemoteAuthenticatedTest):
    def create_info_record(self):
        from random import randint
        blade = 'test-blade-host-name-%s' % (randint(0, 100))
        breachs = randint(0,100)
        dimm = 'test dimm slot %s' % (randint(0,100))
        url = reverse('info:info_creat')
        data = {
            'blade_hostname': blade,
            'breach_count': breachs,
            'dimm_slot': dimm,
        }
        response = self.client.post(url, 
                                    data, 
                                    format='json', 
                                    REMOTE_USER=self.username)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(Info.objects.count(), 1)
        self.assertEqual(Info.objects.get().blade_hostname, blade)

I have this in my settings.py file:

#Authentications
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
}

When I run my test I get this result:

Failure
Traceback (most recent call last):
  File "/myproject/info/tests.py", line 686, in create_info_record
    self.assertEqual(response.status_code, status.HTTP_201_CREATED)
AssertionError: 401 != 201

What am I doing wrong?

UPDATE: After following @henriquesalvaro sage advice I have updated my code to this:

from rest_framework.test import APIClient,APITestCase
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token

class RemoteAuthenticatedTest(APITestCase):
    client_class = APIClient

    def setUp(self):
        self.username = 'mister_neutron'
        self.user = User.objects.create_user(username='mister_neutron',
                                             email='[email protected]',
                                             password='F4kePaSs0d')
        Token.objects.create(user=self.user)
        super(RemoteAuthenticatedTest, self).setUp() 

And I updated my test case to this:

class InfoViewTestCase(RemoteAuthenticatedTest):
    def create_info_record(self):
        from random import randint
        blade = 'test-blade-host-name-%s' % (randint(0, 100))
        breachs = randint(0,100)
        dimm = 'test dimm slot %s' % (randint(0,100))
        url = reverse('info:info_creat')
        data = {
            'blade_hostname': blade,
            'breach_count': breachs,
            'dimm_slot': dimm,
        }
        self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.user.auth_token.key)
        response = self.client.post(url, 
                                    data, 
                                    format='json', 
                                    REMOTE_USER=self.username)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(Info.objects.count(), 1)
        self.assertEqual(Info.objects.get().blade_hostname, blade)

And now my unit test passes.

6
  • rest_framework has an APITestCase with the client already included, you can then override the setUp method to create that class self.user and its token (Token.objects.create(user=self.user), for example). For your test functions you can then use self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.user.auth_token.key) and make the requests as you wish. Commented Nov 1, 2018 at 19:16
  • How do I override the setUp() method? Do I define a setUp() method in my RemoteAuthenticatedTest() class and call it? How do I import the Token class? Commented Nov 1, 2018 at 19:22
  • Yep, you're already doing it in fact. Given your current code, if you just create the user's token on the setUp and then add the credentials to self.client before making the request it should work. Commented Nov 1, 2018 at 19:27
  • What import statement will get me the Token class? Commented Nov 1, 2018 at 19:28
  • 2
    from rest_framework.authtoken.models import Token hopefully will do the trick! Commented Nov 1, 2018 at 19:30

1 Answer 1

3

After following @henriquesalvaro (see comments) sage advice I have updated my code to this:

from rest_framework.test import APIClient,APITestCase
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token

class RemoteAuthenticatedTest(APITestCase):
    client_class = APIClient

    def setUp(self):
        self.username = 'mister_neutron'
        self.user = User.objects.create_user(username='mister_neutron',
                                             email='[email protected]',
                                             password='F4kePaSs0d')
        Token.objects.create(user=self.user)
        super(RemoteAuthenticatedTest, self).setUp() 

And I updated my test case to this:

class InfoViewTestCase(RemoteAuthenticatedTest):
    def create_info_record(self):
        from random import randint
        blade = 'test-blade-host-name-%s' % (randint(0, 100))
        breachs = randint(0,100)
        dimm = 'test dimm slot %s' % (randint(0,100))
        url = reverse('info:info_creat')
        data = {
            'blade_hostname': blade,
            'breach_count': breachs,
            'dimm_slot': dimm,
        }
        self.client.credentials(HTTP_AUTHORIZATION='Token ' + self.user.auth_token.key)
        response = self.client.post(url, 
                                    data, 
                                    format='json', 
                                    REMOTE_USER=self.username)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(Info.objects.count(), 1)
        self.assertEqual(Info.objects.get().blade_hostname, blade)

And now my unit test passes.

Sign up to request clarification or add additional context in comments.

3 Comments

Didn't work for me!
Is self.client an instance of APIClient() or something else?
@BenyaminJafari-aGn self.client is an object of APICLIENT()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.