I am writing a functional test here to check if my API throttling works as expected (there will be a rest at the beginning of each 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 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 looks like a time module, used in DjangoRestFramework throttling.UserRateThrottle somehow gives a value that is always ahead of the time of my test, which causes some accuracy for several seconds.
Based on FreezeGun, Doc time.time() should also be frozen:
After calling the decorator or context manager, 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 was frozen.
But it looks like my case time.time correctly takes the start time of the mocking time-time, but then continues to change with time, which is not expected, it is expected that it will be frozen until the time is redirected manually.
I tried to mock time.time used in UserRateThrottle seperatly using the mock module, but still didn't solve the problem.
----> Any idea what could be the problem, and how can I solve the problem?
Test failure: (after shipment on the last day of the month: line 14 )
self.assertEqual (resp.status_code, 429)
AssertionError: 200! = 429
Source code for the DRF class :
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 ....