I’m trying to get my head around Mock and patch(), but I’m stuck on a somewhat simple example. Say I have the following function in main.py
, which tests if it’s a weekday or not.
from datetime import datetime def is_weekday(): today = datetime.today() return (0 <= today.weekday() < 5)
I want to run my test with two possible outcomes: either False
if I mock Saturday or Sunday or True
if it’s a weekday. Now, I’m clearly not mocking anyting when calling main.is_weekday
so my test currently fails as it’s the weekend. How can I fix that?
from unittest.mock import Mock, patch import pytest import main def test_weekday(): datetime = Mock() tuesday = datetime(year=2019, month=1, day=1) datetime.today.return_value = tuesday with patch.object(datetime, "main.is_weekday", tuesday) as mock_method: expected = True actual = main.is_weekday() # how do I mock datetime.today()? assert actual == expected
Advertisement
Answer
The essential problem is that you’re not patching datetime
in your main
module. The first argument to patch.object
is the thing you want to patch, and since you’re passing in your datetime
Mock object, that doesn’t do you any good.
I would restructure your test like this:
from unittest.mock import Mock, patch from datetime import datetime from mockito import when, ANY import main def test_weekday(): testdate = datetime(year=2019, month=1, day=1) with patch("main.datetime", wraps=datetime) as mock_datetime: mock_datetime.today.return_value = testdate assert main.is_weekday() def test_weekend(): testdate = datetime(year=2019, month=1, day=5) with patch("main.datetime", wraps=datetime) as mock_datetime: mock_datetime.today.return_value = testdate assert not main.is_weekday()
Here, we’re replacing main.datetime
with a mock object, and then configuring it such that calling datetime.today()
in the main
module will return a specific date.
Then we test that the code works as expected for both weekdays and weekends.