2012-02-19 65 views
6

看完這個:How do I mock an open used in a with statement (using the Mock framework in Python)?Python的模擬 - 懲戒幾個開放

我可以在使用嘲笑open函數在python:

with patch(open_name, create=True) as mock_open: 
    mock_open.return_value = MagicMock(spec=file) 
    m_file = mock_open.return_value.__enter__.return_value 
    m_file.read.return_value = 'text1' 

    diffman = Diffman() 
    diffman.diff(path1, path2) 

它運作良好時,我的測試方法使用一個公開聲明。這裏是我測試的方法:

def diff(self, a, b): 
    with open(a, 'r') as old: 
     with open(b, 'r') as new: 
      oldtext = old.read() 
      newtext = new.read() 

oldtext和newtext的值是相同的(這裏是'text1')。

我希望oldtext有'text1',newtext有'text2'。

我該怎麼做?

回答

5

下面是獲取您想要的快捷方式。它有點作弊,因爲被測方法中的兩個文件對象是同一個對象,我們只是在每次讀取之後更改讀取調用的返回值。如果您希望文件對象不同,您可以在多個圖層中使用相同的技術,但這會非常混亂,並且可能會不必要地掩蓋測試的意圖。

替換此行:

 
    m_file.read.return_value = 'text1' 

有:

 
    reads = ['text1', 'text2'] 
    m_file.read.side_effect = lambda: reads.pop(0) 
3

未嘗不是可行的解決方案就是編寫代碼的方式,更好地適合於容易測試它。在'差異'的情況下,似乎很容易(沒有太多其他上下文,誠然)有差異作爲參數已經打開的文件對象。這在代碼中可能只是一個很小的變化,並且使得測試變得非常簡單,因爲您可以在測試時輕鬆地將模擬文件對象提供給diff(),而不是試圖嘲笑相同的兩個實例內置函數作爲上下文經理叫內... ...本身或東西;-)

import StringIO 

diff(a, b): 
    oldtext = a.read() 
    newtext = b.read() 

def test_diff(): 
    a = StringIO.StringIO('text1') 
    b = StringIO.StringIO('text2') 

    res = diff(a, b) 
    <some assertion here> 

會爲你的情況下工作?