2015-12-03 70 views
1

There's a couple of stack overflow posts out there talking about mocking the open call in Python.這很棒,但如果函數接受文件句柄或流對象而不是文件路徑,它並不能真正幫助我。嘲諷文件句柄

我一直使用到目前爲止的一種解決方案是cStringIO對象。但是,我遇到了一個問題。

如果我想測試一下,如果我對某種失敗的登錄正確的文件名(比如如果文件/流是空的,你希望一些類型的數據)

cStringIO 
fd = cStringIO("") 
fd.name = "testing/path" # Throws an AttributeError 

我可以」 t設置名稱屬性,因爲cStringIOStringIO是時隙類。

如果切換到使用open_mock

with mock.patch('__main__.open', mock.mock_open(read_data=''), create=True) as m: 

我碰上

AttributeError: Mock object has no attribute 'tell' 

此時的感覺就像我不得不使用臨時文件,但我想,以避免實際呼喚文件系統如果可能的話。

如何測試接收文件句柄而不必在文件系統上創建實際文件的函數?

+0

正常工作:http://pastebin.com/6QkKxdER,你能顯示測試下你的函數? – falsetru

+0

啊,你明確地設置了'tell'屬性。這也適用於我。您應該將其作爲答案發布。我最終創建了自己的繼承自StringIO和對象的類。我認爲你的答案可能比我最終使用的答案更清晰。 – AlexLordThorsen

回答

1

可以使用Mock.return_value模擬對象明確設置tell屬性:

import mock 

def function_under_test(f): 
    f.tell() # => 0 
    f.read() 
    f.tell() # => 0 
    return f.name 

with mock.patch('__main__.open', mock.mock_open(read_data=''), create=True) as m: 
    with open('/tmp/1') as f: 
     f.name = '/tmp/1' 
     f.tell.return_value = 0 
     assert function_under_test(f) == '/tmp/1' 
0

我走下了創建從StringIO繼承的類的路徑。我花了比我想承認的更多的時間來弄清楚,在Python2.7中,StringIO是一種舊式的類。

class MockFile(StringIO, object): 
    """This is a work around for the fact that StringIO is a slotted class and 
    doesn't have a name attribute. 
    """ 
    name = None 
    def __init__(self, name, buffer_ = None): 
     super(MockFile, self).__init__(buffer_) 
     self.name = name