How to mock/set system date in pytest?

前端 未结 3 1608
南方客
南方客 2021-02-19 07:13

In some of my tests I am having a problem that they fail on Travis because of time and time zone problems, so I want to mock system time for my test. How can I do this?

相关标签:
3条回答
  • 2021-02-19 07:26

    @Brian-Kruger's answer is the best one. I've voted to undelete it. In the meantime...

    Use freezegun (repo).

    From the README:

    from freezegun import freeze_time
    
    @freeze_time("2012-01-14")
    def test():
        assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)
    
    0 讨论(0)
  • 2021-02-19 07:30

    AFAIK, you can't mock builtin methods.

    One approach I have often done is to change my code a bit to not use datetime directly to obtain the date, but a wrapper function somewhere:

    # mymodule.py
    
    def get_today():
       return datetime.date.today()
    

    This makes it trivial to just mock it in your test:

    def test_something():
        with mock.patch('mymodule.get_today', return_value=datetime.date(2014, 6, 2)):
            ...
    

    You can also use the freezegun module.

    0 讨论(0)
  • 2021-02-19 07:48

    There are two ways you can accomplish that:

    1. Create function which you will call instead of datetime.datetime.now() as suggested by Bruno, but here is different implementation:

      import os
      import datetime
      
      def mytoday():
       if 'MYDATE' in os.environ:
           return datetime.datetime.strptime(os.getenv('MYDATE'), '%m-%d-%Y').date()
       else:
           return datetime.date.today()
      

      Then, in your test, you just monkeypatch environment variable:

      import datetime
      
      def test_patched_date(monkeypatch):
          monkeytest.setenv('MYDATE', '05-31-2014')
          assert datetime.date.today() == datetime.date(2014, 5, 31)
      
    2. Monkeypatch the datetime function:

      import datetime
      import pytest
      
      FAKE_TIME = datetime.datetime(2020, 12, 25, 17, 05, 55)
      
      @pytest.fixture
      def patch_datetime_now(monkeypatch):
      
          class mydatetime:
              @classmethod
              def now(cls):
                  return FAKE_TIME
      
          monkeypatch.setattr(datetime, 'datetime', mydatetime)
      
      
      def test_patch_datetime(patch_datetime_now):
          assert datetime.datetime.now() == FAKE_TIME
      
    0 讨论(0)
提交回复
热议问题