Unit testing is very important for confidence in your implementation and early detection of flaws. In case where you want to set some state to unit tests in django where your implementation is dependant on it, the mock library comes in handy.
This becomes tricky when you try to mock python's in built libraries, like for instance datetime. If you try to use a decorator a class or method, you'll run into a TypeError: can't set attributes of built-in/extension type datetime.datetime. To get around this, I used a with block.
with patch('app_name.datetime') as mock_date:
mock_date.utcnow.return_value = UTC_NOW
But the drawback, that block has to be repeated in eery test.
The only way to truly make this more generic and DRY is to sublcass the built-in package you want to mock and sub-class you Test cases from that class.
from datetime import datetime
from mock import patch
from django.test import TestCase
class MockedDatetimeTestCase(TestCase):
"""
Helper testcase to freeze datetime
"""
mocked_utcnow = datetime(2014, 12, 8, 3, 0)
class MockedDatetime(datetime):
"""A python builtin cannot be easily mocked,
so we're subclassing datetime and patching that instead.
"""
@classmethod
def utcnow(cls):
return MockedDatetimeTestCase.mocked_utcnow
def setUp(self):
patcher = patch('app_name.datetime', self.MockedDatetime)
self.addCleanup(patcher.stop)
patcher.start()
You may have noticed that the patcher.stop is called in the setUp() class instead of the tearDown().
This is because, in Django, the tearDown is not guaranteed to be called.