2014-03-12 37 views
6

我剛開始使用python mocking框架。我只想計算一個方法被調用的次數,而不會去除實際調用該方法的效果。使用python mock來計算方法調用次數

例如,在這個簡單的反例,我想增量計數器和跟蹤,它被稱爲:

import unittest 
import mock 


class Counter(object): 
    def __init__(self): 
     self.count = 0 

    def increment(self): 
     self.count += 1 


class CounterTest(unittest.TestCase): 
    def test_increment(self): 
     c = Counter() 
     c.increment() 
     self.assertEquals(1, c.count) 

    def test_call_count(self): 

     with mock.patch.object(Counter, 'increment') as fake_increment: 
      c = Counter() 
      self.assertEquals(0, fake_increment.call_count) 
      c.increment() 
      self.assertEquals(1, fake_increment.call_count) 

      # increment() didn't actually get called. 
      self.assertEquals(1, c.count) # Fails. 

if __name__ == '__main__': 
    unittest.main() 

是否有可能迫使mock後調用模擬的方法註冊了電話,還是隻是表示我想保留模擬功能的效果?

回答

5

只需使用包裝:

c = Counter() 
with mock.patch.object(Counter, 'increment', wraps=c.increment) as fake_increment: 

可以有一些有約束力的問題,如果你初始化c後,傳遞給wraps功能不會知道self

2

我不是假裝超經驗的,但我通過使用函數包裝,而不是默認MagicMock來完成它:

class FuncWrapper(object): 
    def __init__(self, func): 
     self.call_count = 0 
     self.func = func 

    def __call__(self, *args, **kwargs): 
     self.call_count += 1 
     return self.func(*args, **kwargs) 

class CounterTest(unittest.TestCase): 
    def test_call_count(self): 

     c = Counter() 
     new_call = FuncWrapper(c.increment) 
     with mock.patch.object(c, 'increment', new=new_call) as fake_increment: 
      print fake_increment 
      self.assertEquals(0, fake_increment.call_count) 
      c.increment() 
      self.assertEquals(1, fake_increment.call_count) 

      self.assertEquals(1, c.count) # Fails. 

當然,這FuncWrapper是相當小。它只是對呼叫進行計數,然後將流量控制委託給原始功能。如果您需要同時測試其他內容,則需要添加到FuncWrapper類。我也只修補了一個類實例,而不是整個類。主要原因是因爲我需要FuncWrapper中的實例方法。

事實上,我剛開始學習 - 考慮自己警告;-)。