2

There is Django app that uses Django Rest Framework. The settings file contains an object with the settings:

settings.py

REST_FRAMEWORK = {
    ...
    'DEFAULT_THROTTLE_RATES': {
        'burst': '30/second',
    },
    ...
}

The unittest is supposed to test the throttling actually works. However none of the tools provided by Django Test module (SimpleTestCase.settings, override_settings, modify_settings) actually work:

SimpleTestCase.settings

class ThrottlingTest(RestApiTestCase):
    def test_per_second_throttling(self):
        new_config = settings.REST_FRAMEWORK
        new_config['DEFAULT_THROTTLE_RATES']['burst'] = '1/second'
        with self.settings(REST_FRAMEWORK=new_config):
        for _ in range(0, 2):
            response = self.client.get(self.api_reverse('foo'))
        self.assertEqual(response.status_code, 429)  # fails, 200 != 429

override_settings

class ThrottlingTest(RestApiTestCase):
    new_config = settings.REST_FRAMEWORK
    new_config['DEFAULT_THROTTLE_RATES']['burst'] = '1/second'

    @override_settings(REST_FRAMEWORK=new_config)
    def test_per_second_throttling(self):
        for _ in range(0, 2):
            response = self.client.get(self.api_reverse('foo'))
        self.assertEqual(response.status_code, 429)  # fails, 200 != 429

Both methods work fine for primitive variables and lists, however fail for the object.

The docs state:

When given a class, these decorators modify the class directly and return it; they don’t create and return a modified copy of it.

So it actually supposed to work.

Any clues how to handle this?

0leg
  • 13,464
  • 16
  • 70
  • 94
  • well for starters, if throttling is part of the `rest framework`, you shouldn't be writing tests for that, that's the feature of the framework and framework should contain tests for that feature. – Aarif Apr 08 '19 at 07:57
  • Which type of rate throttle implementation are you using - the `AnonRateThrottle` or one of the others? – Will Keeling Apr 08 '19 at 08:58
  • Using this implementation: https://www.django-rest-framework.org/api-guide/throttling/. – 0leg Apr 10 '19 at 07:08

1 Answers1

3

I think this actually a bug/missing feature in Django REST Framework. The settings test tools (SimpleTestCase.settings, override_settings, modify_settings) send out a setting_changed signal and rely on every component to update accordingly.

Django REST Framework does listen to this signal (source), but this has no effect in on the throttle rate because the throttle rate is a class attribute (source).

That being said, I agree with @Aarif that this does not need to be tested because DRF itself has tests covering this feature.

Also, note that you are modifying the existing REST_FRAMEWORK settings dictionary. Create a copy instead:

new_config = settings.REST_FRAMEWORK.copy()
Daniel Hepper
  • 28,981
  • 10
  • 72
  • 75