2015-01-13 52 views
1

因此,我正在處理某個應用程序,該應用程序在導入某些記錄時需要重新計算某些字段。爲了防止數據庫讀取每個檢查,有一個緩存修飾器,因此數據庫讀取僅在導入期間每n秒執行一次。麻煩來自構建測試用例。以下工作確實有效,但它有一個難看的睡眠。使用緩存修飾器在Python中運行單元測試

# The decorator I need to patch 

@cache_function_call(2.0) 
def _latest_term_modified(): 
    return PrimaryTerm.objects.latest('object_modified').object_modified 


# The 2.0 sets the TTL of the decorator. So I need to switch out 
# self.ttl for this decorated function before 
# this test. Right now I'm just using a sleep, which works 

    @mock.patch.object(models.Student, 'update_anniversary') 
    def test_import_on_term_update(self, mock_update): 
     self._import_student() 
     latest_term = self._latest_term_mod() 
     latest_term.save() 
     time.sleep(3) 
     self._import_student() 
     self.assertEqual(mock_update.call_count, 2) 

的裝飾本身看起來如下:

class cache_function_call(object): 
    """Cache an argument-less function call for 'ttl' seconds.""" 
    def __init__(self, ttl): 
     self.cached_result = None 
     self.timestamp = 0 
     self.ttl = ttl 

    def __call__(self, func): 
     @wraps(func) 
     def inner(): 
      now = time.time() 
      if now > self.timestamp + self.ttl: 
       self.cached_result = func() 
       self.timestamp = now 
      return self.cached_result 
     return inner 

我試圖車型的進口之前設置裝飾:

decorators.cache_function_call = lambda x : x 
import models 

但是,即使在該頂部文件,Django仍然在運行我的tests.py之前初始化模型,該函數仍然使用緩存修飾器而不是我的lambda/noop修飾。

什麼是寫這個測試的最好方法,所以我沒有睡眠。我可以在運行我的導入之前設置裝飾器的ttl嗎?

回答

1

您可以稍微改變裝飾器類。

decorators.py模塊級別設置全局

BAILOUT = False 

,並在你的裝飾類,變化:

def __call__(self, func): 
    @wraps(func) 
    def inner(): 
     now = time.time() 
     if BAILOUT or now > self.timestamp + self.ttl: 
      self.cached_result = func() 
      self.timestamp = now 
     return self.cached_result 
    return inner 

然後在你的測試設置decorators.BAILOUT = True,,嘿 - )

相關問題