覆盖测试的 DRF 设置

问题描述 投票:0回答:2

我正在使用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 设置 - 这是我宁愿不做的事情,但它也没有解决我的问题。难道我做错了什么?也许我的解决方案/测试有一些逻辑错误,我正在做一些我不应该做的事情?预先感谢您的所有帮助。

python django django-rest-framework python-3.9 django-rest-framework-simplejwt
2个回答
0
投票

另一种解决方案是直接修改测试设置中的

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
方法中重置任何修改的设置,以避免意外的副作用。


0
投票

发生这种情况是因为多个 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)
© www.soinside.com 2019 - 2024. All rights reserved.