1

测试时,我真的想确保datetime.datetime.now()返回一个特定的日期时间实例。这是我如何在测试中实现这一点,使用pytest的monkeypatch功能:ndb不接受monkeypatched datetime.DateTime

def test_auth_token_create(monkeypatch): 
    newnow = datetime.datetime.now() 
    later = newnow + datetime.timedelta(seconds=10) 

    class fake_dt(datetime.datetime): 
     def __init__(self, year, month, day): 
      super(fake_dt, self).__init__(year, month, day) 

     @classmethod 
     def now(cls): 
      return newnow 

    monkeypatch.setattr(datetime,"datetime", fake_dt) 

user = users.User.new("bob","password") 
token = users.AuthToken.new(user=user, expires=10) 
assert token.expires == later 

但是当我运行我的测试,我得到以下错误:

BadValueError: Expected datetime, got datetime.datetime(2013, 6, 12, 15, 31, 6, 11693) 

此错误是在上升DateTimeProperty的验证方法称为'expires'。

里面的AuthToken类中,有一个叫new类方法,它构造一个实例以下列方式:

expires = datetime.datetime.now() + datetime.timedelta(seconds=expires) 
instance = cls(token=token, user=user, expires=expires) 

在这里,唯一重要的变量是expires这是最初的秒的整数倍,然后通过将timedelta添加到我的monkeypatch返回的datetime.datetime.now值中,然后将其转换为日期时间。

回答

0

该问题是由猴子补丁正在工作引起的。

值为validated通过检查isinstance

def _validate(self, value): 
    if not isinstance(value, datetime.datetime): 
    raise datastore_errors.BadValueError('Expected datetime, got %r' % 
             (value,)) 

所以,如果它是一个真正的子类,isinstance会工作得很好,例如

>>> class A(object): pass 
>>> class B(A): pass 
>>> b = B() 
>>> isinstance(b, A) 
True 

您可能根本不需要在这里使用monkeypatch。相反,您可以在顶层创建自己的自定义datetime.datetime子类,然后使用该子类代替手动使用datetime.datetime

+0

我不得不以某种方式将它作为依赖项注入。但是我发现奇怪的是,在我的'fake_dt'类中,我明确声明它是datetime.datetime的子类。然后,我将datetime.datetime设置为我的fake_tt类,那么在isinstance中不应该评估为True? – bigblind

+0

它应该,但我对“monkeypatch”无法确切地了解足够了解。我敢打赌它会创建自己的自定义类型的对象。 – bossylobster