如何在保留其他方法的同时修补现在的datetime方法?

时间:2015-12-09 07:04:56

标签: python python-2.7 unit-testing mocking

这是我想要测试的功能

from datetime import datetime, timedelta, time
def my_func():
    result_date = datetime.combine(datetime.now(), time.min) + timedelta(days=look_forward)
    ...

这是我的单元测试代码

@patch('batch.mymodule.datetime')
def test_retrieve_data(self, mock_datetime):

   mock_datetime.now = Mock(return_value=datetime.datetime.strptime('Feb 14 2015', '%b %d %Y'))

   my_func

我认为它按预期工作。但是patch也嘲笑了另一种方法combine。我稍后将从my_func获得此异常

BadValueError: Expected datetime, got <MagicMock name='datetime.combine().__add__()' id='4494328976'> 

我可以通过将其添加到单元测试中来解决它:

mock_datetime.combine = datetime.datetime.combine

但这意味着如果使用它,我必须在datetime中修补每个单独的方法。

有没有更好,更简单的替代方案?

2 个答案:

答案 0 :(得分:3)

定义datetime.datetime子类以将其用作模拟对象的类:

class MockDatetime(datetime.datetime):
    fake_now = None

    @classmethod
    def now(cls):
        return cls.fake_now


class TestFoo(unittest.TestCase):
    @patch('mod.datetime', MockDatetime)
    def test_retrieve_data(self):
        MockDatetime.fake_now = datetime.datetime(2015, 2, 14)
        my_func()

DEMO:http://asciinema.org/a/63nrqzrysunyeq76xl72f943k

答案 1 :(得分:1)

这不能回答你的问题,但我认为值得一提的是另一种方法。对于我的项目,我使用了freezegun

from freezegun import freeze_time
import datetime

class SomeTest(TestCase):

    @freeze_time("2015-08-10 00:00:00")
    def some_test_case(self):
        print(datetime.now())

  2015-08-10 00:00:00