Search code examples
pythonunit-testingpytestpatchpytest-mock

how to mock patch `today` in pytest python?


Suppose I have a module that checks a date is today (this is a simplified code)

# my_module.py
import datetime


def is_today(input_date):
    return input_date == datetime.date.today()

I want to test this function

# test_my_module.py
import datetime
from unittest.mock import patch

from my_module import is_today


def test_is_today():
    cases = [
        {'input_date': datetime.date(2022, 5, 14), 'expected_output': True, 'today': datetime.date(2022, 5, 14)},
        {'input_date': datetime.date(2022, 5, 14), 'expected_output': False, 'today': datetime.date(2022, 5, 12)}
    ]
    for case in cases:
        with patch('my_module.datetime.date.today', lambda x: case['today']):
            assert is_today(case['input_date']) == case['expected_output']

But when I run pytest test_my_module.py, I get FAILED test_my_module.py::test_is_today - TypeError: can't set attributes of built-in/extension type 'datetime.date'

Any idea how to do it?

Also does anybody know how to do it with pytest-mock and which method is prefered?


Solution

  • You could patch the entire datetime:

        for case in cases:
            class FakeDatetime:
                class date:
                    def today(): return case['today']
            with patch('my_module.datetime', FakeDatetime)
    

    The limitation is that you lose all other functionality of datetime.