2015-01-13 3 views
1

그래서 특정 레코드를 가져올 때 일부 필드를 다시 계산해야하는 응용 프로그램에서 작업하고 있습니다. 각 검사마다 데이터베이스 읽기를 방지하기 위해 캐싱 데코레이터가 있으므로 가져 오는 동안 n 초마다 한 번만 데이터베이스를 읽습니다. 테스트 케이스를 구축 할 때 문제가 발생합니다. 다음은 작동하지만 추한 수면을 보입니다.파이썬에서 캐싱 데코레이터가있는 단위 테스트 실행하기

# 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) 

는 장식 자체처럼 보이는 다음

decorators.cache_function_call = lambda x : x 
import models 

그러나 심지어 상단의 :

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 

나는 모델의 가져 오기 전에 장식을 설정하려고했습니다 파일, 장고 아직 내 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을 설정

을하고, -)