1

我基本上想打开TokenAuthentication,但仅用于2个单元测试。我目前看到的唯一选择是使用@override_settings(...)替换REST_FRAMEWORK设置值。运行时单元测试Django Rest框架身份验证

REST_FRAMEWORK_OVERRIDE={ 
    'PAGINATE_BY': 20, 
    'TEST_REQUEST_DEFAULT_FORMAT': 'json', 
    'DEFAULT_RENDERER_CLASSES': (
     'rest_framework.renderers.JSONRenderer', 
     'rest_framework_csv.renderers.CSVRenderer', 
    ), 
    'DEFAULT_AUTHENTICATION_CLASSES': (
     'rest_framework.authentication.TokenAuthentication', 
    ), 
    'DEFAULT_PERMISSION_CLASSES': (
     'rest_framework.permissions.IsAuthenticated', 
    ), 
} 

@override_settings(REST_FRAMEWORK=REST_FRAMEWORK_OVERRIDE) 
def test_something(self): 

这是行不通的。我可以在修饰器之前和之后打印设置,并看到值已更改,但django似乎并未尊重它们。它允许所有使用测试客户端或DRF APIClient对象发送的请求无需验证。当我预计401未经授权时,我收到200条回应。

如果我在config文件夹的test_settings.py文件中插入相同的字典,一切都按预期工作。然而就像我说过的,我只想打开几个单元测试的认证,而不是全部。我的想法是,Django在初始化之后永远不会重新访问DRF的设置。所以即使设置值是正确的,它们也不会被使用。

有没有人遇到这个问题,并找到了解决办法?或解决方法?

+0

使用提供'从rest_framework.settings导入api_settings'审查源代码会给你一个提示如何覆盖: https://开头github.com/tomchristie/django-rest-framework/blob/master/rest_framework/settings.py – petkostas 2015-03-31 11:47:04

+0

我刚刚发现这个问题,https://github.com/tomchristie/django-rest-framework/issues/2466看起来像我的问题可能还没有解决:/ – 2015-03-31 18:32:21

回答

1

只是想我会提到我是如何解决这个问题的。这不是很好,如果有人有任何建议来清理它们,它们是非常值得欢迎的!正如我前面提到的,我遇到的问题记录在这里(https://github.com/tomchristie/django-rest-framework/issues/2466),但修复不太清楚。除了重新加载DRF视图模块之外,我还必须重新加载应用程序视图模块才能使其工作。

import os 
import json 
from django.conf import settings 
from django.test.utils import override_settings 
from django.utils.six.moves import reload_module 

from rest_framework import views as drf_views 
from rest_framework.test import force_authenticate, APIRequestFactory, APIClient 

from apps.contact import views as cm_views 
from django.core.urlresolvers import reverse 
from django.test import TestCase 
from unittest import mock 

REST_FRAMEWORK_OVERRIDE={ 
'PAGINATE_BY': 20, 
'TEST_REQUEST_DEFAULT_FORMAT': 'json', 
'DEFAULT_RENDERER_CLASSES': (
    'rest_framework.renderers.JSONRenderer', 
    'rest_framework_csv.renderers.CSVRenderer', 
), 
'DEFAULT_AUTHENTICATION_CLASSES': (
    'rest_framework.authentication.TokenAuthentication', 
), 
'DEFAULT_PERMISSION_CLASSES': (
    'rest_framework.permissions.IsAuthenticated', 
), 
} 

def test_authenticated(self): 
    with override_settings(REST_FRAMEWORK=REST_FRAMEWORK_OVERRIDE): 
     # The two lines below will make sure the views have the correct authentication_classes and permission_classes 
     reload_module(drf_views) 
     reload_module(cm_views) 
     from apps.contact.views import AccountView 
     UserModelGet = mock.Mock(return_value=self.account) 
     factory = APIRequestFactory() 
     user = UserModelGet(user='username') 
     view = AccountView.as_view() 

     # Test non existent account 
     path = self.get_account_path("1thiswillneverexist") 
     request = factory.get(path) 
     force_authenticate(request, user=user) 
     response = view(request, account_name=os.path.basename(request.path)) 
     self.assertEquals(response.status_code, 200, "Wrong status code") 
     self.assertEqual(json.loads(str(response.content, encoding='utf-8')), [], "Content not correct for authenticated account request") 
    # Reset the views permission_classes and authentication_classes to what they were before this test 
    reload_module(cm_views) 
    reload_module(drf_views) 
+0

我还应该提到,导入不喜欢重新加载模块... – 2015-04-01 20:40:17

0

以下解决方法很适合我:

from rest_framework.views import APIView 
from rest_framework.permissions import IsAuthenticatedOrReadOnly 
from rest_framework.authentication import TokenAuthentication 

try: 
    from unittest.mock import patch 
except ImportError: 
    from mock import patch 

@patch.object(APIView, 'authentication_classes', new = [TokenAuthentication]) 
@patch.object(APIView, 'permission_classes', new = [IsAuthenticatedOrReadOnly]) 
class AuthClientTest(LiveServerTestCase): 
    # your tests goes here