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='mister_neutron@example.com',
                                             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='mister_neutron@example.com',
                                             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.

Benyamin Jafari
  • 27,880
  • 26
  • 135
  • 150
Red Cricket
  • 9,762
  • 21
  • 81
  • 166
  • `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. – henriquesalvaro Nov 01 '18 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? – Red Cricket Nov 01 '18 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. – henriquesalvaro Nov 01 '18 at 19:27
  • What import statement will get me the `Token` class? – Red Cricket Nov 01 '18 at 19:28
  • 2
    `from rest_framework.authtoken.models import Token` hopefully will do the trick! – henriquesalvaro Nov 01 '18 at 19:30
  • Yep that does it! Thanks you are awesome sir! – Red Cricket Nov 01 '18 at 19:32

1 Answers1

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='mister_neutron@example.com',
                                             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.

Red Cricket
  • 9,762
  • 21
  • 81
  • 166