0

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?

Amin Ba
  • 1,603
  • 1
  • 13
  • 38

1 Answers1

1

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.

MB-F
  • 22,770
  • 4
  • 61
  • 116
  • generally, is this a good idea to use patch from unittest in pytest? can we do the same with pytest-mock? – Amin Ba Apr 08 '22 at 21:26
  • 1
    Since unittest is part of the Python standard library, it should be ok to use. At least, that's what I usually do... still, someone may prove me wrong :) – MB-F Apr 08 '22 at 21:32
  • This is a similar question but with a new problem https://stackoverflow.com/questions/71845390/how-to-partially-mock-patch-datetime-in-pytest-python – Amin Ba Apr 12 '22 at 15:30
  • The answer to that question makes me facepalm myself :) I kinda thought we were patching the `datetime` class, but we're actually patching the entire module... this is a bit of an overkill and it would be indeed better just patch `datetime.date`. – MB-F Apr 12 '22 at 18:43