如何为受身份验证保护的REST API编写Django单元测试?

时间:2018-11-01 19:08:00

标签: python django

我已经看过关于SO的两个答案,这些答案可能已经有了我的答案,但是坦率地说,我只是不理解它们。这些SO帖子为:Django Rest Framework API Authentication TestDjango authenticate unit test

两个SO问题都使用不同的方法。

我正在尝试使用的方法是这样。我创建了此类:

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()

我的单元测试如下:

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)

我的settings.py文件中有此文件

#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',
    ),
}

运行测试时,我得到以下结果:

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

我在做什么错了?

更新:在遵循@henriquesalvaro的明智建议之后,我已将代码更新为:

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() 

然后我将测试用例更新为此:

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)

现在我的单元测试通过了。

1 个答案:

答案 0 :(得分:0)

在遵循@henriquesalvaro(请参阅评论)贤哲建议之后,我已将代码更新为:

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() 

然后我将测试用例更新为此:

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)

现在我的单元测试通过了。