2015-05-20 42 views
9

模擬(http://mock.readthedocs.org/en/latest/index.html)是python單元測試的一個很棒的工具。它可以方便地嘲笑一種方法或類或字典。但我遇到了一個問題,我找不到一個直接的方法來處理模擬。如何讓MagicMock的行爲像字典?

這是函數進行測試:

def function_to_be_tested(id, responses): 
    if not id in responses: 
     print '%s not exist'%pole_id 
     return 

    if id in responses.redundantErrorResponses: 
     print '%s is redundant'%pole_id 
     return 

    do_something() 

參數響應是像對象的字典,其具有一些其他屬性(例如redundantErrorResponses),所不同的dict固有特徵。現在我想構建一個模擬響應,讓id in responses爲True並且id in responses.redundantErrorResponses爲False。這是我做的:發生

pole_id = 30 
pole_value = 100 
pole_dic = {pole_id:pole_value} 
mock_responses = MagicMock() 
mock_responses.__getitem__.side_effect = lambda k: pole_dic[k] 
mock_responses.__iter__.side_effect = iter(pole_dic) 
mock_responses.redundantErrorResponses = {} 

但是錯誤:

function_to_be_tested(pole_id, mock_responses) 

>>30 not exist 

那麼,如何構建一個MagicMock對象同時可以遍歷像字典或我如何可以構建一個字典同時支持MagicMock功能(自由添加屬性)?

+0

它應該是'''function_to_be_tested(pole_id,mock_responses)'''? – wwii

回答

11

爲什麼要亂用__iter__?在我看來,要惹__contains__

>>> import mock 
>>> m = mock.MagicMock() 
>>> d = {'foo': 'bar'} 
>>> m.__getitem__.side_effect = d.__getitem__ 
>>> m.__iter__.side_effect = d.__iter__ 
>>> m['foo'] 
'bar' 
>>> 'foo' in m 
False 
>>> m.__contains__.side_effect = d.__contains__ 
>>> 'foo' in m 
True 
1

你總是可以創建一些愚蠢的類來做同樣的事情。

In [94]: class MockResponses(dict): 
    ....:  @property 
    ....:  def redundantErrorResponses(self): 
    ....:   return {} 
+0

我真的很接近推薦同樣的事情:-)。一個註釋 - 你甚至在這裏甚至不需要一個「屬性」 - 你可以只有'redundantErrorResponses'作爲一個類的屬性,因爲你只打算創建一個實例... – mgilson

+0

是的,這是我的初始解決方案,但我只想知道「如何構建一個MagicMock對象,同時可以像字典一樣迭代」。 @ mgilson的回答是正確的。 – lengxuehx