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.