我意識到這是一個非常奇怪的事情要做 - 這主要是爲了簡化我的單元測試。把開放()從非文件讀入?
我有一個類,其__init__
需要一個文件名作爲參數,它從open()
s和讀取一堆數據。如果我能以某種方式「欺騙」open()
從字符串對象讀取而不實際將臨時文件寫入磁盤,那真是太棒了。
這是可能的,如果是這樣,我該怎麼辦呢?
我意識到這是一個非常奇怪的事情要做 - 這主要是爲了簡化我的單元測試。把開放()從非文件讀入?
我有一個類,其__init__
需要一個文件名作爲參數,它從open()
s和讀取一堆數據。如果我能以某種方式「欺騙」open()
從字符串對象讀取而不實際將臨時文件寫入磁盤,那真是太棒了。
這是可能的,如果是這樣,我該怎麼辦呢?
你可以猴子補丁包含運行測試之前的類模塊,測試後恢復:
def my_fake_open(fake_filename):
return object_with_read_and_close_that_will_feed_correct_data()
def test_something(self):
module_containing_test.open = my_fake_open
...run test...
del module_containing_test.open
退房,如果你不想寫自己的模仿對象的mock library 。
讀得有點太快,我以爲答案會在io.stringIO
,它允許你創建一個類似文件的對象與字符串的內容。
但是你想要的是一個對象,它傳遞給標準的open
函數實際上會從你的字符串的內容中產生一個類似文件的對象。
事情是,open
需要一個字符串(或文件描述符),但其他任何東西都會暫停問題。
所以我不認爲這種方式是實用的。
但實際上,這不是很難創建一個使用tempfile
文件:
with tempfile.NamedTemporaryFile() as tmp_file:
tmp_file.write(your_string)
yourmodule.YourClass(tmp_file.name)
(如果你使用的是Windows,你可能想要發送的名稱爲它打開之前delete=False
,靠近玩。 )
另一種方法可能是更改API:如果所有init都使用該名稱來打開文件,爲什麼不直接傳遞類似文件的對象。
這*完全*無益。我試圖欺騙open()來生成實際上由'str'或'bytearray'或其他任何文件系統文件支持的'io.stringIO',爲了這個問題我不能改變我打入的代碼。這可能是不可能的,但我想我會問。 – Schilcote
我讀得太快了,對不起。這是第二次嘗試。 –
只需改變'__init__'的定義。其他任何東西(臨時文件,替換全局變量或管道)將是一個可怕的黑客攻擊。 – o11c
如果你真的不能改變'__init__'(爲什麼不呢?爲什麼非單元測試調用者不能輕易地傳遞任意數據而不是文件名?),這個問題可能是http://的重複stackoverflow.com/questions/5237693/mocking-openfile-name-in-unit-tests。 – Random832