最近これ系のことばかり書いてます。
pythonでdatetime.dateをpatchする
datetime.dateをpatchする話の続きとisinstanceのオーバーライド
datetime.date.todayの結果をfreezegunを使って固定する
以下はうまくいきませんが、minimockでできないかって試してみたときのメモです。
import datetime from unittest import TestCase from dateutil.relativedelta import relativedelta from minimock import Mock, restore class DateTodayMockTest(TestCase): def setUp(self): datetime.date.today = Mock("datetime.date.today", returns=datetime.date(2014, 1, 1)) def tearDown(self): restore() def test_today(self): today = datetime.date.today() self.assertEquals(today.year, 2014) self.assertEquals(today.month, 1) self.assertEquals(today.day, 1) tomorrow = today + relativedelta(days=1) self.assertEquals(tomorrow.year, 2014) self.assertEquals(tomorrow.month, 1) self.assertEquals(tomorrow.day, 2) day_after_day = tomorrow + relativedelta(days=1) self.assertEquals(day_after_day.year, 2014) self.assertEquals(day_after_day.month, 1) self.assertEquals(day_after_day.day, 3)
わかる人はすぐにわかると思いますが、どうなるかというと、以下のエラーになります。
TypeError: can't set attributes of built-in/extension type 'datetime.date'
なんとかminimockでできないかなと思ってこんなのも試してみてました。
import sys import datetime from unittest import TestCase from dateutil.relativedelta import relativedelta from minimock import Mock, restore def get_today(): return datetime.date.today() class DateTodayMockTest3(TestCase): def setUp(self): current_module = sys.modules[__name__] current_module.get_today = Mock("get_today", returns=datetime.date(2014, 1, 1)) def tearDown(self): restore() def test_today(self): today = get_today() self.assertEquals(today.year, 2014) self.assertEquals(today.month, 1) self.assertEquals(today.day, 1) tomorrow = today + relativedelta(days=1) self.assertEquals(tomorrow.year, 2014) self.assertEquals(tomorrow.month, 1) self.assertEquals(tomorrow.day, 2) day_after_day = tomorrow + relativedelta(days=1) self.assertEquals(day_after_day.year, 2014) self.assertEquals(day_after_day.month, 1) self.assertEquals(day_after_day.day, 3)
不恰好ですが、これは一応うまくいきます。
テストで差し替えられるようにするためだけに、datetime.date.todayを呼び出すだけの関数を定義してます。