2012-11-13 11 views
28

Bir yoklama işlevini sınamak için, bir alt işlevin çağrılması ile uğraşmak istiyorum, böylece ilk çağrıldığı zaman başarısız olur ve ikinci kez çağrılırsa başarılı olur.python mock side_effect veya return_value aramaya bağlı call_count

poll_function(var1): 
    value = sub_function(var1) # First call will return None 
    while not value: 
     time.sleep(POLLING_INTERVAL) 
     value = sub_function(var1) # A subsequent call will return a string, e.g "data" 
    return value 

bu mock çerçevede bir Mock nesne ile yapmak mümkün mü: İşte bunun bir çok basitleştirilmiş versiyonu? Mock nesnelerinin bir şekilde kullanabilmem call_count özniteliğine sahip olduğunu biliyorum.

Şu anda ben maymun yama sub_function() için kullandıkları özel bir sahte nesnesi oluşturarak bunu çözdük, ancak bunu yapmanın daha iyi daha az ayrıntılı bir şekilde olmalıdır hissediyorum:

def test_poll(): 
    class MyMock(object):              

     def __init__(self, *args):            
      self.call_count = 0             

     def sub_function(self, *args, **kwargs):        
      if self.call_count > 1:            
       return "data"    
      else:                
       self.call_count += 1           
       return None 

    my_mock = MyMock()               
    with patch('sub_function', my_mock.sub_function):   
     ok_(poll_function())   

cevap

42

ben anlamak Sorunuzu doğru olarak setting side_effect to an iterable ile yapıyorsunuz. sizin basit durum için:

>>> mock_poll = Mock(side_effect=chain(['first'], cycle(['others']))) 
+1

Evet, teşekkürler, bu oldukça iyi çalıştı:

>>> mock_poll = Mock(side_effect=[None, 'data']) >>> mock_poll() None >>> mock_poll() 'data' 

aramaların sınırsız sayıda için izin vermek istiyorsanız, itertoolscycle ve chain işlevlerini kullanın. Bununla birlikte, dikkate değer bir şey, bu _doesn't_ 'mock 'sürümü' 0.7.2 'üzerinde çalışmaktadır, o sırada ne olduğumu. Bu özelliği düzgün kullanmak için '0.8.0' sürümüne yükseltmek zorunda kaldım. – imolit