如何重写测试设置中的一个值

How can I rewrite one value in the settings for the test

如何在测试设置中重写 'user': '5/分钟' on 'user': '2/day'

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES': {
         'user': '5/minute'
    }
}

如何使用@override_settings 或 mb 进行上下文管理? 我只需要在一次测试中应用它,我不能重写整个字典

def test_mytest(self):
    value = settings.REST_FRAMEWORK
    value['DEFAULT_THROTTLE_RATES'] = {'user':'2/day'}

    data1 = {}
    data2 = {}
    data3 = {}

with self.settings(REST_FRAMEWORK=value):
    resp1 = self.client.post(self.url, data1, format='json')
    resp2 = self.client.post(self.url, data1, format='json')
    resp3 = self.client.post(self.url, data1, format='json')

assert resp3.status_code == 429, resp3.data

但是没有429错误,虽然值已经改变了

解决方案 1:使用 @override_default() 包装器

您想将包装函数应用到您希望用此值覆盖的 viewset

from rest_framework.throttling import UserRateThrottle

class UserViewSet(viewsets.ViewSet):

    @api_view(['PUT'])
    @throttle_classes([UserRateThrottle])
    @override_settings(REST_FRAMEWORK['DEFAULT_THROTTLE_RATES']['user'] = "2/day")
    def update(self, request, pk=None):
        ...

在您希望应用此覆盖自定义值的任何视图或视图集之前添加包装。

您也想在 settings.py:

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.AnonRateThrottle',
        'rest_framework.throttling.UserRateThrottle'
    ),
    'DEFAULT_THROTTLE_RATES': {
        'anon': '100/day',
        'user': '13500/day'
    }
}

解决方案 2:自定义节流 class

但是,如果您希望在测试环境中使用不同的节流率,也许可以在 settings.py 中尝试以下操作:

TEST = True ## <-- Set to False when not in testing!!

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': (
        'rest_framework.throttling.CustomUserRateThrottle'
    )
}

并指定您自己的自定义节流 class:

from django.conf import settings

class CustomUserRateThrottle(throttling.UserRateThrottle):
    if settings.TEST:
        THROTTLE_RATES = 'DEFAULT_THROTTLE_RATES': {
            'user': '13500/day',
        }
    else:
        THROTTLE_RATES = 'DEFAULT_THROTTLE_RATES': {
            'user': '2/day',
        } 
    return settings.TEST # <-- Custom throttling classes must always return either True or False, so this makes sense.

解决方案 3:直接在您的 "testing shell":

包括我们上面定义的自定义包装器,但这次是在 test.py 中的 test_something() 方法中:

from django.conf import settings
from django.test import TestCase

class TestCase(TestCase):

    def test_something(self):

       with self.settings(REST_FRAMEWORK = ['DEFAULT_THROTTLE_RATES']['user'] = '13500/day'):


       # START TESTING HERE WITH TEST SETTINGS

根据您的用例,您可以采用以下方式之一:

建议 1: 如果你想 覆盖一些特定测试用例中的设置 你可以使用 @override_settings 装饰器。但是,如果您希望对所有测试用例都这样做,那么这没有任何意义,如果是这种情况,那么您可以遵循建议 2.

建议 2 : 这是更通用和有效的解决方案。

您可以为各种 运行ning 环境(在设置 python 模块内)设置多个设置文件,如下所示:

  1. base.py(包含您所有的基本设置)
  2. local.py(从此处导入 * 和 override/add 特定于 local/dev 环境的设置)
  3. test.py(从此处导入 * 和 override/add 特定于测试环境的设置)
  4. 您还可以在 prod.py 或其他内容中针对生产环境进行特定设置。

使用此设置可以 运行 测试 python manage.py test --settings=yourproject.settings.test

    from unittest import mock

    @mock.patch('rest_framework.throttling.SimpleRateThrottle.get_rate')
    def test_api(self, get_rate):
        get_rate.return_value = '1/minute'

        from rest_framework.settings import api_settings
        print(api_settings.DEFAULT_THROTTLE_RATES)
        print(api_settings.user_settings)


        url = 'api'

        response = self.client.get(url)
        self.assertEqual(response.status_code, HTTP_200_OK)

        response = self.client.get(url)
        self.assertEqual(response.status_code, HTTP_429_TOO_MANY_REQUESTS)