我正在使用Python 3.9、Django 3.2、DRF 3.12.4。我正在使用简单的 JWT 添加 JWT 身份验证方法。要测试我的身份验证方法,我需要设置
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
),
我想避免编辑我的设置文件并将所有更改保留在我的测试文件中。那是因为我有单独的本地和生产设置,并且本地设置使用假身份验证后端。当我在本地设置中设置上述身份验证类时,所有测试都通过了。
我尝试使用@override_settings:
@override_settings(
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_simplejwt.authentication.JWTAuthentication",
),
}
)
它似乎工作正常 - 当我在测试中打印设置时:
from django.conf import settings
from rest_framework.settings import api_settings
...
def setUp(self):
print(settings.REST_FRAMEWORK)
print(api_settings.DEFAULT_AUTHENTICATION_CLASSES)
我明白了
{'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework_simplejwt.authentication.JWTAuthentication',)}
[<class 'rest_framework_simplejwt.authentication.JWTAuthentication'>]
但是,测试没有通过 - 我从假身份验证后端收到错误,就好像设置毕竟没有被覆盖一样。我还尝试直接编辑 django.conf 设置 - 这是我宁愿不做的事情,但它也没有解决我的问题。难道我做错了什么?也许我的解决方案/测试有一些逻辑错误,我正在做一些我不应该做的事情?预先感谢您的所有帮助。
另一种解决方案是直接修改测试设置中的
REST_FRAMEWORK
设置。
这允许您在测试用例持续时间内动态更改设置。
from django.conf import settings
from rest_framework.test import APITestCase
class MyTests(APITestCase):
def setUp(self):
# Modify REST_FRAMEWORK settings for JWT authentication in the setup
settings.REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] = ["rest_framework_simplejwt.authentication.JWTAuthentication"]
def tearDown(self):
# Optionally reset modified settings in tearDown to avoid side effects
settings.REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] = original_authentication_classes
def test_my_view(self):
# Your test code here
请谨慎使用此方法,因为它直接修改全局设置,并可能会影响应用程序的其他测试或部分。请务必确保在
tearDown
或 tearDownClass
方法中重置任何修改的设置,以避免意外的副作用。
发生这种情况是因为多个 DRF 基类在类上存储初始值。
您可以像这样更新各种缓存值:
from rest_framework.generics import GenericAPIView
from rest_framework.settings import api_settings
from rest_framework.test import APIRequestFactory
from rest_framework.views import APIView
GenericAPIView.filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
GenericAPIView.pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
APIView.renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
APIView.parser_classes = api_settings.DEFAULT_PARSER_CLASSES
APIView.authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
APIView.throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
APIView.permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
APIView.content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
APIView.metadata_class = api_settings.DEFAULT_METADATA_CLASS
APIView.versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
APIRequestFactory.renderer_classes_list = api_settings.TEST_REQUEST_RENDERER_CLASSES
APIRequestFactory.default_format = api_settings.TEST_REQUEST_DEFAULT_FORMAT
如果您希望在使用
override_settings
时能够自动发生这种情况,请为 setting_changed
添加信号监听器。
from django.test.signals import setting_changed
from rest_framework.generics import GenericAPIView
from rest_framework.settings import api_settings
from rest_framework.test import APIRequestFactory
from rest_framework.views import APIView
def reload_drf_settings(*args, **kwargs):
setting = kwargs['setting']
if setting == 'REST_FRAMEWORK':
api_settings.reload()
GenericAPIView.filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
GenericAPIView.pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
APIView.renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
APIView.parser_classes = api_settings.DEFAULT_PARSER_CLASSES
APIView.authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
APIView.throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
APIView.permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
APIView.content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
APIView.metadata_class = api_settings.DEFAULT_METADATA_CLASS
APIView.versioning_class = api_settings.DEFAULT_VERSIONING_CLASS
APIRequestFactory.renderer_classes_list = api_settings.TEST_REQUEST_RENDERER_CLASSES
APIRequestFactory.default_format = api_settings.TEST_REQUEST_DEFAULT_FORMAT
setting_changed.connect(reload_drf_settings)