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