Reputation: 333
Can someone help me to unit test this line of code?
from datetime import datetime, timedelta, timezone
def get_timestamp_plus_100_year():
return int((datetime.now(timezone.utc) + timedelta(days=100 * 365)).timestamp())
I try this, but I don't know how to assign the values:
@patch("src.shared.utils.timedelta")
@patch("src.shared.utils.datetime")
def test_get_timestamp_now_plus_100_years(self, mock_datetime, mock_timedelta):
mock_datetime.now.return_value = 2021-09-14 15:54:25.284087+00:00
mock_timedelta.return_value = 36500 days, 0:00:00
self.assertEqual(
get_timestamp_plus_100_year(),
int((mock_datetime.now.return_value
+ mock_timedelta.return_value).timestamp_return_value ),
)
Upvotes: 1
Views: 1736
Reputation: 10699
Correct the implementation first. As pointed out by @MrFuppes, not all years are 365 days. Assuming today is 2021-9-15
, your original implementation would result to:
>>> datetime.now(timezone.utc) + timedelta(days=100 * 365)
datetime.datetime(2121, 8, 22, 9, 19, 30, 468735, tzinfo=datetime.timezone.utc)
Here, you can see that instead of the expected 2121-9-15
, what we got was 2121-8-22
.
Option 1: Using datetime.replace() to replace the year
with year+100
>>> (dt := datetime.now(timezone.utc)).replace(year=dt.year + 100)
datetime.datetime(2121, 9, 15, 9, 24, 52, 139984, tzinfo=datetime.timezone.utc)
Option 2: Using dateutil.relativedelta.relativedelta to add +100
years. This requires pip install python-dateutil
.
>>> datetime.now(timezone.utc) + relativedelta(years=100)
datetime.datetime(2121, 9, 15, 9, 28, 16, 789807, tzinfo=datetime.timezone.utc)
Then, you don't need to mock the timedelta
(or relativedelta
in our corrected code) since its value will always be 100 years. You just need to mock the current date via datetime.now()
since it is the base of the addition and we need to assert the result.
Assuming this is the file tree:
.
├── src.py
└── test_src.py
src.py
from datetime import datetime, timezone
from dateutil.relativedelta import relativedelta
def get_timestamp_plus_100_year():
return int((datetime.now(timezone.utc) + relativedelta(years=100)).timestamp())
from datetime import datetime
import unittest
from unittest.mock import patch
from dateutil.relativedelta import relativedelta
from src import get_timestamp_plus_100_year
class TestDates(unittest.TestCase):
@patch("src.datetime")
def test_get_timestamp_now_plus_100_years(self, mock_datetime):
frozen_dt = datetime(year=2021, month=9, day=15)
mock_datetime.now.return_value = frozen_dt
# Solution 1.1
self.assertEqual(
get_timestamp_plus_100_year(),
int((frozen_dt + relativedelta(years=100)).timestamp()),
)
# Solution 1.2
frozen_dt_100 = datetime(year=2121, month=9, day=15) # Since we already know the value of +100 years, we can just define it here
self.assertEqual(
get_timestamp_plus_100_year(),
int(frozen_dt_100.timestamp()),
)
This requires freezegun via pip install freezegun
from datetime import datetime
import unittest
from freezegun import freeze_time
from src import get_timestamp_plus_100_year
@freeze_time("2021-09-15") # Either here
class TestDates(unittest.TestCase):
@freeze_time("2021-09-15") # Or here
def test_get_timestamp_now_plus_100_years_2(self):
frozen_dt_100 = datetime(year=2121, month=9, day=15) # Since we already know the value of +100 years, we can just define it here
self.assertEqual(
get_timestamp_plus_100_year(),
int(frozen_dt_100.timestamp()),
)
Upvotes: 2