在DRF中测试节流的正确方法是什么?

Gle*_*len 6 python testing django throttling django-rest-framework

在DRF中测试节流的正确方法是什么?我在网上找不到这个问题的任何答案。我希望对每个端点进行单独的测试,因为每个端点都有自定义请求限制(ScopedRateThrottle)。

重要的是它不会影响其他测试-它们必须以某种方式运行而不会受到限制和限制。

yof*_*fee 6

一个简单的解决方案是使用油门类patchget_rate方法。感谢tprestegard 的评论

在我的情况下,我有一个自定义类:

from rest_framework.throttling import UserRateThrottle

class AuthRateThrottle(UserRateThrottle):
    scope = 'auth'
Run Code Online (Sandbox Code Playgroud)

在您的测试中:

from unittest.mock import patch
from django.core.cache import cache
from rest_framework import status

class Tests(SimpleTestCase):
    def setUp(self):
        cache.clear()

    @patch('path.to.AuthRateThrottle.get_rate')
    def test_throttling(self, mock):
        mock.return_value = '1/day'
        response = self.client.post(self.url, {})
        self.assertEqual(
            response.status_code,
            status.HTTP_400_BAD_REQUEST,  # some fields are required
        )
        response = self.client.post(self.url, {})
        self.assertEqual(
            response.status_code,
            status.HTTP_429_TOO_MANY_REQUESTS,
        )
Run Code Online (Sandbox Code Playgroud)

还可以修补 DRF 包中的方法以更改标准油门类的行为: @patch('rest_framework.throttling.SimpleRateThrottle.get_rate')


Dan*_*ski 5

就像人们已经提到的那样,这并不完全属于单元测试的范围,但是,简单地做这样的事情怎么样:

from django.core.urlresolvers import reverse
from django.test import override_settings
from rest_framework.test import APITestCase, APIClient


class ThrottleApiTests(APITestCase):
    # make sure to override your settings for testing
    TESTING_THRESHOLD = '5/min'
    # THROTTLE_THRESHOLD is the variable that you set for DRF DEFAULT_THROTTLE_RATES
    @override_settings(THROTTLE_THRESHOLD=TESTING_THRESHOLD)
    def test_check_health(self):
        client = APIClient()
        # some end point you want to test (in this case it's a public enpoint that doesn't require authentication
        _url = reverse('check-health')
        # this is probably set in settings in you case
        for i in range(0, self.TESTING_THRESHOLD):
            client.get(_url)

        # this call should err
        response = client.get(_url)
        # 429 - too many requests
        self.assertEqual(response.status_code, 429)
Run Code Online (Sandbox Code Playgroud)

此外,关于您对副作用的担忧,只要您在setUpor 中创建用户setUpTestData,测试就会被隔离(应该如此),因此无需担心“脏”数据或范围。

关于测试之间清除缓存,我想补充cache.clear()tearDown或试图清除节流定义的特定键

  • 不错的解决方案,但这部分显然是错误的: range(0, self.TESTING_THRESHOLD) as self.TESTING_THRESHOLD 是一个字符串 (5认同)