I'm writing here a functional test to check if my API throttling is working as expected (will be rest at the beginning of every month).
Testing Class:
class ApiThrottlingTest(ThrottlingBaseTest):
def test_throttling_purchaser_case(self):
now = datetime.datetime(year=2015, month=1, day=10, hour=6, minute=6, second=3)
last_day_of_current_month = datetime.datetime(year=2015, month=1, day=31, hour=23, minute=59, second=59)
first_day_of_next_month = datetime.datetime(year=2015, month=2, day=1, hour=0, minute=0, second=0)
with freeze_time(now) as frozen_datetime:
for i in xrange(3):
resp = self._project_details_request()
self.assertEqual(resp.status_code, 200)
resp = self._project_details_request()
self.assertEqual(resp.status_code, 429)
frozen_datetime.move_to(last_day_of_current_month)
resp = self._project_details_request()
# the test fails at this level
self.assertEqual(resp.status_code, 429)
frozen_datetime.move_to(first_day_of_next_month)
resp = self._project_details_request()
self.assertEqual(resp.status_code, 200)
The test works fine if: last_day_of_current_month = datetime.datetime(... second=0)
but will fail if: last_day_of_current_month = datetime.datetime(... second=59)
After debugging it seems like the time
module used in DjangoRestFramework throttling.UserRateThrottle
is in somehow giving a value that's always ahead of the fronzen time in my test, which is causing a precision issue of some seconds.
Based on FreezeGun Doc time.time()
should be also frozen:
Once the decorator or context manager have been invoked, all calls to datetime.datetime.now(), datetime.datetime.utcnow(), datetime.date.today(), time.time(), time.localtime(), time.gmtime(), and time.strftime() will return the time that has been frozen.
But it looks like im my case time.time
takes correctly the start time of the mocked datetime but then keep changing over time which is not expected, it's expected to be frozen till the time is manually forwarded.
I tried to mock time.time
used in UserRateThrottle
seperatly using mock
module but still did not solve the issue.
----> Any idea what could be the issue, and how could be possibly resolved?
Test Fail: (after time is forwarded to the last day of the month: line 14)
self.assertEqual(resp.status_code, 429)
AssertionError: 200 != 429
The DRF class source code:
class SimpleRateThrottle(BaseThrottle):
...
cache = default_cache
timer = time.time
cache_format = 'throttle_%(scope)s_%(ident)s'
def __init__(self):
....
def allow_request(self, request, view):
...
self.now = self.timer() # here timer() returns unexpected value in test
....
SimpleRateThrottle
manually using monkey patching using the pythonmock
module but still have the same problem!!! – Rozanne