Mocking time issue in django test: time seems not to be frozen using freezegun
我在这里写一个功能测试来检查我的API限制是否按预期工作(将在每个月的开始时休息)。
测试类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | 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) |
如果符合以下条件,则测试工作正常:
但如果:
在调试之后,似乎DjangoRestFramework
基于FreezeGun Doc
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.
但看起来我的情况
我尝试使用
---->任何想法可能是什么问题,怎么可能解决?
测试失败:(在时间转发到该月的最后一天之后:第14行)
self.assertEqual(resp.status_code, 429)
AssertionError: 200 != 429
DRF类源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 .... |
你需要用FreezeGun的time.time覆盖
这里发生的事情是,feezegun可能会覆盖Python的时间模块。 但是,
因此,
编辑:
你应该这样做 - 在FreezeGun被激活之后:
1 2 | former_timer = SimpleRateThrottle.timer SimpleRateThrottle.timer = time.time |
一旦你的测试结束(在tearDown或任何等价物中):
1 | SimpleRateThrottle.timer = former_timer |
请注意,您也可以使用猴子修补lib来为您处理。