datetime.dateをpatchする話の続きとisinstanceのオーバーライド

前回の続き

datetime.dateをpatchしたらrelativedeltaで問題がありました。
なので、FakeDateでisinstanceをオーバーライドしてみます。

isinstanceをオーバーライドするには、メタクラスで__instancecheck__を実装します。

from unittest import TestCase
from dateutil.relativedelta import relativedelta
from mock import patch
import datetime


class DateTodayMockTest(TestCase):
    def setUp(self):

        self.original_date = datetime.date

        class FakeDateMeta(type):
            def __instancecheck__(cls, instance):
                return isinstance(instance, self.original_date)

        class FakeDate(datetime.date):
            @classmethod
            def today(cls):
                return cls(2014, 1, 1)

            __metaclass__ = FakeDateMeta

        patcher = patch('datetime.date', FakeDate)
        self.addCleanup(patcher.stop)
        patcher.start()

    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)

できたけどなんかめんどくさいですね。他の方法を検討したほうがいいかも