Explain Codes LogoExplain Codes Logo

Trying to mock datetime.date.today(), but not working

python
mocking
unittest
testing
Anton ShumikhinbyAnton ShumikhinΒ·Mar 8, 2025
⚑TLDR

To mock datetime.date.today(), employ unittest.mock.patch specifically on the imported date class within the module under test. Here's a quick snippet:

from unittest.mock import patch from datetime import date import my_module # The module invoking datetime.date.today() with patch('my_module.date.today') as mock_today: mock_today.return_value = date(2023, 1, 1) # "We live in the future now 😎" # "Who's the Time Lord now?" my_module's datetime.date.today() now thinks it's 2023-01-01

Inside the patch context, my_module.date.today() returns a fixed date object, cutting ties with real world dates and ensuring our testing is hermetically sealed in predictability.

Broadening your mocking horizon

I know you love unittest.mock.patch, but we've got another friend who's just as cool, if not a bit more ice cold: freezegun.

Chilling out with freezegun 🧊⏲️

Freezegun has one mission in life: manage time. To install this time lord, just pip install freezegun. With @freeze_time("YYYY-MM-DD") you get the keys to your own TARDIS:

from freezegun import freeze_time import my_module @freeze_time("2023-01-01") def test_something(): assert my_module.some_function() == expected_result # "Who says time travel isn't possible?"

Consider freezegun your time-freezing omnipotent deity that makes time constants across all modules! Perfect for testing time-sensitive functions.

Patch's roommate: MagicMock

If you're dealing with dynamic dates or multiple return values, `unittest.mock.MagicMock' can add that pinch of magic to your test:

from unittest.mock import patch, MagicMock from datetime import datetime, timedelta with patch('my_module.date.today', new_callable=MagicMock) as mock_today: mock_today.side_effect = [datetime.today(), datetime.today() + timedelta(days=1)] # First call gets you today, next call? "Time travel to tomorrow!"

Traps to look out for

We've all been lulled by that false sense of security only to have Python imports surprise us!

Patching Imports: Always patch date.today() where it's used, not where it's originally defined

- βœ… Right way: Patch `'my_app.my_module.date.today'` - ❌ Nuh-uh: Patching `'datetime.date.today'`

Assert your dominance: Make sure you're in control! Assert the results in your test cases to make sure the mocked date.today() is strutting as expected.

Scope your mocks: Use @patch('your_module.datetime') for proper scoping and ensure your mock doesn't overstay its welcome and spill to other test cases.

Mock like an expert: advanced tips

Comprehensive patching for interconnected modules

We sometimes deal with interconnected modules, each calling datetime functions. Freezegun shines here by freezing time consistently across all modules.

All wrapped up: Mock wrapping

When you need the original behavior of other datetime functions, the wraps argument is your answer:

from unittest.mock import patch, MagicMock from datetime import datetime def custom_today(): return datetime(2023, 1, 1) # "I always love starting the New Year on a high note" with patch('my_module.datetime', wraps=datetime) as mock_dt: mock_dt.date.today = MagicMock(side_effect=custom_today) # "I've only reshaped the fabric of time for today()"

Testing edge cases

Don't forget those corner cases: last day of the month or year. Mock these specific dates to ensure your code doesn't pull a pumpkin-at-midnight Cinderella move.