Trying to mock datetime.date.today(), but not working
There are a few problems.
First of all, the way you're using mock.patch
isn't quite right. When used as a decorator, it replaces the given function/class (in this case, datetime.date.today
) with a Mock
object only within the decorated function. So, only within your today()
will datetime.date.today
be a different function, which doesn't appear to be what you want.
What you really want seems to be more like this:
@mock.patch('datetime.date.today')
def test():
datetime.date.today.return_value = date(2010, 1, 1)
print datetime.date.today()
Unfortunately, this won't work:
>>> test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "build/bdist.macosx-10.6-universal/egg/mock.py", line 557, in patched
File "build/bdist.macosx-10.6-universal/egg/mock.py", line 620, in __enter__
TypeError: can't set attributes of built-in/extension type 'datetime.date'
This fails because Python built-in types are immutable - see this answer for more details.
In this case, I would subclass datetime.date myself and create the right function:
import datetime
class NewDate(datetime.date):
@classmethod
def today(cls):
return cls(2010, 1, 1)
datetime.date = NewDate
And now you could do:
>>> datetime.date.today()
NewDate(2010, 1, 1)
Python: Mocking datetime.date.today()
It is just because by @patch('mymodule.dt.date')
you are patching the original date
reference in datetime
module. In this context dt.date(2016, 1, 10)
is a MagicMock
where the name is date()
.
From this you have today_string_dt_date()
will return a date().strftime()
MagicMock
.
I admit that is a little bit twisted and it is for this kind of things that I try avoid complicated paths in patch: my rules are
- Try to patch just the root reference.
- If you cannot follow 1 (module with
from a import b
) just patch the module reference and never browse from it.
Python: How do I mock datetime.utcnow()?
in your test file:
from yourfile import get_report_month_key
import mock
import unittest
from datetime import datetime
class TestCase(unittest.TestCase):
@mock.patch('yourfile.datetime')
def test_dt(self, mock_dt):
mock_dt.utcnow = mock.Mock(return_value=datetime(1901, 12, 21))
r = get_report_month_key()
self.assertEqual('190112', r)
How to mock python's datetime.now() in a class method for unit testing?
You could use freezegun :
from freezegun import freeze_time
def test():
assert datetime.datetime.now() != datetime.datetime(2012, 1, 14)
with freeze_time("2012-01-14"):
assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)
assert datetime.datetime.now() != datetime.datetime(2012, 1, 14)
It basically mocks datetime
module calls.
How to mock datetime.date.today() method in Django 1.5.5 tests
My investigations into this are in the question as a set of edits, but the long and short of this is that changes to the to_python method between 1.4 and 1.5 mean that anything that is neither a valid datetime.date nor datetime.datetime must be a string in order to pass through.
It looks (without too much further digging) as if the django.utils.encoding.smart_str
method was removed in 1.5, and although it's been replaced by smart_text
, this never made it into the to_python
method.
I have raised a ticket in the django Trac instance, https://code.djangoproject.com/ticket/21523
I have also created a patch for this issue - but obviously this may never make it in (and the patch is for 1.5.x, which is already out-of-date, so I really wouldn't count on this making it in).
[EDIT 1: a solution!]
There is a solution ;-) - I have done a write up here - http://tech.yunojuno.com/mocking-dates-with-django - the key is overriding the FakeDate instancecheck method, so that when comparing a real datetime.date to a FakeDate you get True. I have put together a gist with some sample FakeDate classes and associated tests for reference - https://gist.github.com/hugorodgerbrown/7750432
Related Topics
How to Print Unicode Character in Python
How to Limit Concurrency with Python Asyncio
Weird Try-Except-Else-Finally Behavior with Return Statements
Datetime to String with Series in Pandas
Windows Is Not Passing Command Line Arguments to Python Programs Executed from the Shell
Adding a Module (Specifically Pymorph) to Spyder (Python Ide)
Get the Key Corresponding to the Minimum Value Within a Dictionary
Sorting Columns in Pandas Dataframe Based on Column Name
How to Overload Python Assignment
How to Add an Image in Tkinter
Pandas Dataframe to List of Dictionaries
Pandas Convert Dataframe to Array of Tuples
Selenium Compound Class Names Not Permitted
What Is the Internal Precision of Numpy.Float128
When to Use "While" or "For" in Python
What Is the '@=' Symbol for in Python
Insert an Element at a Specific Index in a List and Return the Updated List