假设我有以下Event
模型:
from django.db import models
import datetime
class Event(models.Model):
date_start = models.DateField()
date_end = models.DateField()
def is_over(self):
return datetime.date.today() > self.date_end
我想Event.is_over()
通过创建一个在将来(今天+
1或某天)结束的事件进行测试,并对日期和时间进行打桩,以便系统认为我们已经达到了该将来的日期。
就python而言,我希望能够存根所有系统时间对象。这包括datetime.date.today()
,datetime.datetime.now()
和任何其他标准日期/时间对象。
这样做的标准方法是什么?
编辑
:由于我的答案是此处接受的答案,因此我正在对其进行更新,以使所有人都知道在此同时创建了更好的方法,这是freezegun库:https
://pypi.python.org/pypi/freezegun 。当我想影响测试时间时,会在所有项目中使用此功能。看看它。
原始答案:
更换内部零件总是很危险的,因为它可能会带来讨厌的副作用。因此,您真正想要的是让猴子修补尽可能地局部。
我们使用了Michael Foord出色的模拟库:http
://www.voidspace.org.uk/python/mock/
,该库具有@patch
装饰器,该装饰器修补某些功能,但是Monkey修补器仅位于测试功能的范围内,并且一切功能超出范围后会自动恢复。
唯一的问题是内部datetime
模块是用C实现的,因此默认情况下您将无法进行猴子补丁。我们通过制作 可以 模拟的自己的简单实现来解决此问题。
总体解决方案是这样的(示例是在Django项目中使用的验证器函数,用于验证日期在将来)。请注意,我是从一个项目中拿出来的,但是拿出了一些不重要的东西,因此在复制粘贴时,事情可能实际上不起作用,但是我希望您明白了,
首先,我们datetime.date.today
在一个名为的文件中定义自己的非常简单的实现utils/date.py
:
import datetime
def today():
return datetime.date.today()
然后,我们在以下代码中为此验证器创建单元测试tests.py
:
import datetime
import mock
from unittest2 import TestCase
from django.core.exceptions import ValidationError
from .. import validators
class ValidationTests(TestCase):
@mock.patch('utils.date.today')
def test_validate_future_date(self, today_mock):
# Pin python's today to returning the same date
# always so we can actually keep on unit testing in the future :)
today_mock.return_value = datetime.date(2010, 1, 1)
# A future date should work
validators.validate_future_date(datetime.date(2010, 1, 2))
# The mocked today's date should fail
with self.assertRaises(ValidationError) as e:
validators.validate_future_date(datetime.date(2010, 1, 1))
self.assertEquals([u'Date should be in the future.'], e.exception.messages)
# Date in the past should also fail
with self.assertRaises(ValidationError) as e:
validators.validate_future_date(datetime.date(2009, 12, 31))
self.assertEquals([u'Date should be in the future.'], e.exception.messages)
最终的实现如下所示:
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError
from utils import date
def validate_future_date(value):
if value <= date.today():
raise ValidationError(_('Date should be in the future.'))
希望这可以帮助
问题内容: 我正在尝试为超过5个小时的旧窗口小部件编写Django查询,但我有点迷失了。窗口小部件模型具有一个用窗口小部件的创建时间填充的。 问题答案: 如果是模型的名称,并且具有名为的DateTimeField属性,则查询为: 请注意,这意味着“创建的内容少于”。
问题内容: 我有一个网络表单,用户可以在其中从日历弹出窗口中选择日期,并从下拉菜单中选择时间。目前,我正在尝试使用Date对象存储日期。 这个对象的输出类似于: 1970年1月1日,00:00:00 GMT 我真正想做的是将其分开并以类似 27/02/2013 的格式存储日期,并以24小时格式(例如 23:45) 将时间作为单独的对象。我不确定如何用Java做到这一点。 使用SimpleDateF
我希望这些事件在秒后打印出来。 Spring WebFlux/Reactor可能吗?
问题内容: 我有一个带有几个视图的django应用程序,这些视图通过POST请求接受json对象。json对象是中等复杂的,具有几层嵌套,因此我正在使用json库解析raw_post_data,如下所示: 接下来,我要为这些视图编写测试。不幸的是,我不知道如何将json对象传递给客户端。这是我的代码的最简单的版本: 当我运行测试时,它失败并显示: 如何在Client.post方法中传递JSON对象
问题内容: 如何对日期和/或日期时间对象列表进行排序?接受的答案在这里是不是为我工作: 问题答案: 你得到,因为它运行 在原地 ,这意味着它不返回任何东西,但修改列表本身。您只需要呼叫而无需再次分配。 有一个内置函数,该函数返回列表的排序版本-也会执行您想要的操作。
问题内容: 我的模型是: 我可以使用以下查询找出大于的对象: 我想找到所有大于一年的物体。 如何根据和之间的差异找出对象? 问题答案: 通用解决方案: 您可以更改日期,然后对照(与@Anonymous在他的评论中建议的内容非常接近)进行检查: PostgreSQL特定解决方案: 如果您正在使用,则可以从此答案中得到另一个选择: