我最近學到了關於unittest.monkey.patch
及其變體,我想用它來單元測試文件讀取函數的原子性。但是,該補丁似乎沒有任何效果。如何使用unittest修補方法io.RawIOBase.read?
這是我的設置。備受矚目的方法大致是這樣(abriged):
#local_storage.py
def read(uri):
with open(path, "rb") as file_handle:
result = file_handle.read()
return result
以及進行單元測試(也abriged)模塊:
#test/test_local_storage.py
import unittest.mock
import local_storage
def _read_while_writing(io_handle, size=-1):
""" The patch function, to replace io.RawIOBase.read. """
_write_something_to(TestLocalStorage._unsafe_target_file) #Appends "12".
result = io_handle.read(size) #Should call the actual read.
_write_something_to(TestLocalStorage._unsafe_target_file) #Appends "34".
class TestLocalStorage(unittest.TestCase):
_unsafe_target_file = "test.txt"
def test_read_atomicity(self):
with open(self._unsafe_target_file, "wb") as unsafe_file_handle:
unsafe_file_handle.write(b"Test")
with unittest.mock.patch("io.RawIOBase.read", _read_while_writing): # <--- This doesn't work!
result = local_storage.read(TestLocalStorage._unsafe_target_file) #The actual test.
self.assertIn(result, [b"Test", b"Test1234"], "Read is not atomic.")
這樣,補丁應該確保你每次嘗試讀取它,文件在實際讀取之前和之後被修改,就像它同時發生一樣,從而測試讀取的原子性。
單元測試目前成功,但我已經用打印語句驗證了補丁函數實際上並沒有被調用,所以文件從不會獲得額外的寫入(它只是說「測試」)。我也將代碼修改爲非故意的。
所以我的問題:如何修補local_storage模塊內的IO句柄的read
函數?我讀過別處,人們傾向於取代open()函數來返回類似於StringIO
的東西,但我不明白這是怎麼解決這個問題的。
我需要支持Python 3.4及更高版本。
你看,看看如何嘲笑'open'?閱讀[this](http://www.voidspace.org.uk/python/mock/helpers.html#mock-open)。但是,有時候,我也看到'StringIO'用來不直接寫入文件系統。 – idjaw
在Python 3中,它支持[here](https://docs.python.org/3/library/unittest.mock.html#mock-open) – idjaw
我剛纔寫了一個解決方案,解釋瞭如何處理背景經理。它周圍的細節與你所要做的並不完全相關,但它解釋了上下文管理器的本質並使用了開放性。希望它有幫助:http:// stackoverflow。com/a/33652204/1832539 – idjaw